2013-12-19 92 views
1

你能承担我的最佳以上ellegant方式, List<Product> allProducts转换为Map<Integer, List<Product>>产品由ProductNumber分组。转换列表<Product>地图<整数,列表<Product>>

例如我的产品POJO。

public class Product{ 
.. 
private Integer productCode; 
private String productName; 
... 
//getters, setters 
} 

这是我的尝试,但我觉得它不那么ellegant:

public Map<Integer, List<Product>> getProductsByIndex (List<Product> products){ 
     Map<Integer, List<Product>> resultMap = new HashMap<>(); 
     Set<Integer> productCodes = getProductCodes(products); 

     for(Integer productCode: productCodes){ 
      List<Product> productsByCode = new ArrayList<>(); 
      for(Product product : products){ 
       if(productCode == product.getCode()){ 
        productsByCode.add(product);  
       } 
      } 
      resultMap.put(productCode, productsByCode); 
     } 
     return resultMap; 
    } 

    public Set<Integer> getProductCodes (List<Product> products){ 
     Set<Integer> productCodes = new HashSet<>(); 
     for(Product product: products){ 
      productCodes.add(product.getCode()); 
     } 
     return productCodes; 
    } 

回答

1

您的解决方案是不是线性的,并与数据的显著量太慢。只需使用简单的方法:

public Map<Integer, List<Product>> getProductsByIndex (List<Product> products){ 
    Map<Integer, List<Product>> resultMap = new HashMap<>(); 

    for(Product product: products){ 
     List<Product> productsByCode = resultMap.get(product.getCode()); 
     if (productsByCode == null) { 
      productByCode = new ArrayList(); 
      resultMap.put(product.getCode(), productByCode); 
     } 
     productsByCode.add(product);  
    } 
    return resultMap; 
} 
4
for (Product p: products) { 
    List<Product> l = productsByCode.get(p.getCode()); 
    if (l == null) { 
     l = new ArrayList<>(); 
     productsByCode.put(p.getCode(), l); 
    } 
    l.add(p); 
} 

这就是你需要:)

+1

正确的答案,但您应该注意,'productsByCode'是您的结果,而不是原始代码中的'resultMap'。 – jwueller

+0

+1,或许不像以前那样*优雅*就像下面的Java 8解决方案一样易于理解 – user1781290

+2

@ user1781290:它也适用于目前正在使用的几乎所有Java版本,显着提高了此代码段/回答的实用性。 – jwueller

0

我会做这样的:

Map<Integer, List<Product>> resultMap = new HashMap<>(); 
for (Product product : products) { 
    List<Product> productList = resultMap.get(product.getCode()); 
    if (productList == null) { 
     productList = new ArrayList<>(); 
     resultMap.put(product.getCode(), productList); 
    } 
    productList.add(product); 
} 
0
public Map<Integer, List<Product>> getProductsByIndex (List<Product> products){ 
    Map<Integer, List<Product>> resultMap = new HashMap<>(); 

    for(Product product : products) { 
     if(!resultMap.containsKey(product.getProductCode()) { 
      resultMap.put(product.getProductCode(), new ArrayList<Product>(); 
     } 

     resultMap.get(product.getProductCode()).add(product); 
    } 

    return resultMap; 

} 
6

的Java 8解决方案:

Map<Integer, List<Product>> productsByCode = products.stream() 
        .collect(Collectors.groupingBy(Product::getProductCode)); 
+0

如果您已经在使用Java 8,那么最好的解决方案! – bobbel

+1

我想upvote这优雅,但我不知道它是否会工作。注意自我,阅读新的Java 8功能的东西:) –

+2

@TimB http://www.tryjava8.com/app/snippets/52b2f6ebe4b0f5090255ba3d – user2336315

1

如果您使用Eclipse Collections可以产品转换为ListIterable,并使用groupBy()方法。

ListMultimap<Integer, Product> productsByCode = 
    products.groupBy(Product::getProductCode); 

一个Multimap<Integer, Product>在概念上类似于Map<Integer, List<Product>>但它是这个用例进行了优化。您仍然可以拨打get()以获得具有特定代码的产品。

ListIterable<Product> productsWithCode = productsByCode.get(someProductCode); 

但是,通过使用一个Multimap,你不必担心空。当产品代码不存在时,get()将返回空集合,而不是空。 Multimap也有便利的方法,如containsKeyAndValue()

boolean b = productsByCode.containsKeyAndValue(someProductCode, product); 

如果您不能转换产品从ListListIterable,那么你可以使用ListAdapter得到相同的API。

ListMultimap<Integer, Product> productsByCode = 
    ListAdapter.adapt(products).groupBy(Product::getProductCode); 

在Java 8之前的Java版本,该方法参考成为匿名Function

ListMultimap<Integer, Product> productsByCode = 
    products.groupBy(new Function<Product, Integer>() 
    { 
     @Override 
     public Integer valueOf(Product product) 
     { 
      return product.getProductCode(); 
     } 
    }); 

注:我的Eclipse藏品的参与者。

相关问题