Используйте потоки java для преобразования списка SimpleEntry имени бренда и продукта в карту имени бренда в список продуктов

#java #java-stream

Вопрос:

Я хочу преобразовать список SimpleEntry<String, Product> в a Map<String, List<Product> . Строка-это название бренда, и у каждого названия бренда есть продукты. Итак, я хочу преобразовать List<SimpleEntry<> в Map<String, List<Product> то место на карте, где я получаю список продуктов для названия бренда.

В настоящее время я использую следующий код, но я думаю, что это можно сделать и с потоками

 //List<AbstractMap.SimpleEntry<String, Product>> listOfSimpleEntries = new ArrayList<>() is a list of simple Entries 
//e.g. 
//nike, productA 
//adidas, productB,
//nike, productC

Map<String, List<Product>> brandToProductsMap = new HashMap<>();
for (AbstractMap.SimpleEntry<String, Product> simpleEntry : listOfSimpleEntries) {
    if (!brandToProductsMap.containsKey(simpleEntry.getKey())) {
        brandToProductsMap.put(simpleEntry.getKey(), new ArrayList<>());
    }
    brandToProductsMap.get(simpleEntry.getKey()).add(simpleEntry.getValue());
}
 

Я попытался заменить приведенный выше код потоками, как показано ниже, но я получаю java.util.Список массивов не может быть приведен к продукту

 Map<String, List<Product>> brandToProductsMap = listOfSimpleEntries.stream().collect(Collectors.groupingBy(
          w -> w.getKey(), Collectors.mapping(x -> x.getValue(), Collectors.toList())));
 

Может кто-нибудь, пожалуйста, указать мне, чего мне здесь не хватает? Спасибо.

Редактировать 2 Код, который я написал, работает как отдельная программа, но не является частью проекта. Я обнаружил, что в целевой папке код скомпилирован, как показано ниже, что кажется неправильным.

         Map<String, List<Product>> brandToProductsMap = (Map)listOfSimpleEntries.stream().collect(Collectors.groupingBy((w) -> {
            return (String)w.getKey();
        }, Collectors.mapping((x) -> {
            return (Product)x.getValue();
        }, Collectors.toList())));
        Iterator var5 = brandToProductsMap .entrySet().iterator();
 

Комментарии:

1. предполагая CompatibleProduct , что это опечатка Product , это невозможно воспроизвести.

2. Да, это была опечатка. Спасибо, что указали на это.

Ответ №1:

Вы можете сделать:

 List<AbstractMap.SimpleEntry<String, Product>> entries = Arrays.asList(
        new AbstractMap.SimpleEntry<>("Nike", new Product("ProductA")),
        new AbstractMap.SimpleEntry<>("Adidas", new Product("ProductB")),
        new AbstractMap.SimpleEntry<>("Nike", new Product("ProductC"))
);

Map<String, List<Product>> brandNameToProduct = entries.stream()
        .collect(Collectors.groupingBy(e -> e.getKey(), 
                Collectors.mapping(e -> e.getValue(), Collectors.toList())));

System.out.println(brandNameToProduct);
 

Выход:

 {Nike=[Product(name=ProductA), Product(name=ProductC)], Adidas=[Product(name=ProductB)]}
 

Редактировать:

Я думаю, что ты поступил точно так же, как и я, так что, возможно, твоя идея сошла с ума.

Комментарии:

1. Да, я сделал точно то же самое, и если я запущу его как отдельную программу, он будет работать нормально, но не как часть проекта. Я не знаю, в чем проблема с моим интеллектом.

Ответ №2:

Надеюсь, что приведенный ниже фрагмент кода может помочь:

 public static void main(String[] args) {
        List<SimpleEntry<String, Product>> list = new ArrayList<SimpleEntry<String, Product>>();
        list.add(SimpleEntry.of("electronic", new Product(1, "SmartPhone")));
        list.add(SimpleEntry.of("electronic", new Product(2, "Laptop")));
        list.add(SimpleEntry.of("office", new Product(3, "Book")));
        list.add(SimpleEntry.of("office", new Product(4, "Pencil")));
        list.add(SimpleEntry.of("office", new Product(5, "Notes")));
        list.add(SimpleEntry.of("garden", new Product(6, "Rosesmany")));
        list.add(SimpleEntry.of("garden", new Product(7, "Soil Mix")));
        list.add(SimpleEntry.of("garden", new Product(8, "Pressure Sprayer")));
        
        System.out.println("Before:");
        list.stream().forEach(System.out::println);
        
        Map<String, List<Product>> map = list.stream().collect(
                    groupingBy(entry -> entry.getKey(), mapping(entry -> entry.getEntry(), toList())) 
                );
        
        System.out.println("After:");
        map.forEach((k, v) -> System.out.println("Key : "   k   ", Value : "   v));
}
 

Простой вход

 public class SimpleEntry<K, V> {
    private K key;
    private V entry;
        
    static public <K, V> SimpleEntry<K, V> of (K key, V entry)
    {
        SimpleEntry<K, V> sEntry = new SimpleEntry<>();
        sEntry.setKey(key);
        sEntry.setEntry(entry);
        return sEntry;
    }
    //getters/setters...
}
 

Я написал это, и это сработало для меня:

 Before:
electronic - Product(1, SmartPhone)
electronic - Product(2, Laptop)
office - Product(3, Book)
office - Product(4, Pencil)
office - Product(5, Notes)
garden - Product(6, Rosesmany)
garden - Product(7, Soil Mix)
garden - Product(8, Pressure Sprayer)
After:
Key : electronic, Value : [Product(1, SmartPhone), Product(2, Laptop)]
Key : garden, Value : [Product(6, Rosesmany), Product(7, Soil Mix), Product(8, Pressure Sprayer)]
Key : office, Value : [Product(3, Book), Product(4, Pencil), Product(5, Notes)]
 

Комментарии:

1. Спасибо, Хоуи. Ваш код работает и мой, и тот, который добавлен наиболее нужным кроликом, тоже работает при выполнении в отдельном классе, но в рамках проекта я получаю сообщение об ошибке. Итак, я пытаюсь выяснить, какие настройки мне нужно изменить, чтобы сделать это правильным.