2013-12-19 5 views
1

Не могли бы вы предположить, мне лучше или более ellegant способ, чтобы преобразовать List<Product> allProducts в Map<Integer, List<Product>> продуктов, сгруппированных по ProductNumber.Список Преобразовать <Product> к карте <Integer, Список <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

Я хочу возвысить это для элегантности, но я понятия не имею, будет ли это работать. Обратите внимание на себя, читайте новый функциональный материал 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() вернет пустую коллекцию, если код продукта не существует, а не null. Multimap также имеет удобные методы, такие как containsKeyAndValue().

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

Если вы не можете преобразовать продукты из List в ListIterable, то вы можете использовать ListAdapter, чтобы получить тот же API.

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

С версии Java до Java 8, эталонный метод становится анонимным Function.

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

Примечание: Я коммиттер для коллекций Eclipse.

Смежные вопросы