2013-12-19 91 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藏品的參與者。

相關問題