Java stream collect to hashmap

преобразовать список в hashmap в java, используя stream api [duplicate]

Встроенный div является уродцем сети и amp; должен быть избит до тех пор, пока он не станет промежутком (по крайней мере 9 раз из 10) .

. отвечает на исходный вопрос .

18 ответов

На основе Collectors документации это так же просто, как:

Map result = choices.stream().collect(Collectors.toMap(Choice::getName, Function.identity())); 

В качестве примечания, даже после Java 8, JDK по-прежнему не может участвовать в конкурсе на краткость. Альтернатива Guava выглядит настолько читаемой: Maps.uniqueIndex(choices, Choice::getName) . – Bogdan Calmac 3 March 2015 в 18:59

@BogdanCalmac Это довольно тривиально написать такой метод uniqueIndex() самостоятельно в Java 8. – herman 28 August 2016 в 21:37

Есть ли преимущества использования функции. Я имею в виду, это — & gt; он короче – shabunc 30 May 2017 в 12:49

@shabunc Я не знаю никакой пользы и фактически использую it -> it сам. Function.identity() используется здесь главным образом потому, что он используется в ссылочной документации, и это все, что я знал о лямбдах во время написания – zapl 30 May 2017 в 12:57

@zapl, о, на самом деле выясняется, что есть причины этого — stackoverflow.com/questions/28032827/… – shabunc 30 May 2017 в 13:39

Используйте getName () как ключ и сам выбор как значение карты:

Map result = choices.stream().collect(Collectors.toMap(Choice::getName, c -> c)); 

Пожалуйста, напишите некоторое описание, чтобы пользователь мог понять. – Mayank Jain 28 February 2015 в 08:38

Это очень плохо, здесь нет более подробных сведений, потому что мне нравится этот ответ лучше всего. – MadConan 24 November 2015 в 14:50

Он равен choices.stream().collect(Collectors.toMap(choice -> choice.getName(),choice -> choice)); Первая функция для ключа, вторая функция для значения – waterscar 6 January 2016 в 08:29

Я знаю, как легко видеть и понимать c -> c , но Function.identity() несет большую семантическую информацию. Обычно я использую статический импорт, так что я могу просто использовать identity() – Hank D 9 April 2016 в 21:06

Вот еще один случай, если вы не хотите использовать Collectors.toMap ()

Map result = choices.stream().collect(HashMap::new, (m, c) -> m.put(c.getName(), c), (m, u) -> <>); 

Что лучше использовать тогда Collectors.toMap() или наш собственный HashMap, как вы показали в приведенном выше примере? – Swapnil Gangrade 18 July 2016 в 14:22

В этом примере приведен пример того, как разместить на карте что-то еще. Я хотел, чтобы значение не предоставлялось вызовом метода. Благодаря! – th3morg 21 April 2017 в 01:51

Третья функция аргумента неверна. Там вы должны предоставить некоторую функцию для объединения двух Hashmaps, что-то вроде Hashmap :: putAll – jesantana 21 July 2017 в 08:34

Я напишу, как преобразовать список в карту с помощью дженериков и инверсии элемента управления. Просто универсальный метод!

Возможно, у нас есть список целых чисел или список объектов. Итак, вопрос заключается в следующем: что должно быть ключом к карте?

public interface KeyFinder

теперь с помощью инверсии управления:

 static Map listToMap(List list, KeyFinder finder) < return list.stream().collect(Collectors.toMap(e ->finder.getKey(e) , e -> e)); > 

Например, если у нас есть объекты книги, этот класс должен выбрать ключ для карты

public class BookKeyFinder implements KeyFinder  < @Override public Long getKey(Book e) < return e.getPrice() >> 

Если вы не против использовать сторонний lib ( Vavr (ранее известный как Javaslang) ), вы можете использовать мощные новые неизменные коллекции:

// import javaslang.collection.*; Map map = list.toMap(choice -> Tuple.of(choice.getName(), choice)); 

Там также много методов для преобразования Java-коллекций вперед и назад.

Пожалуйста, прочитайте подробнее о новых коллекциях здесь.

Отказ от ответственности: я являюсь создателем Vavr.

Я пытался это сделать и обнаружил, что, используя ответы выше, при использовании Functions.identity() для ключа к карте, у меня возникли проблемы с использованием локального метода, такого как this::localMethodName , чтобы фактически работать из-за ввода вопросов .

Functions.identity() фактически что-то делает для ввода в этом случае, поэтому метод будет работать только путем возврата Object и принятия параметра Object

. Чтобы решить эту проблему, Я закончил тем самым Functions.identity() и использовал s->s .

Итак, мой код, в моем случае, чтобы перечислить все каталоги внутри каталога, и для каждого из них используйте имя каталога как ключ к карту, а затем вызвать метод с именем каталога и вернуть коллекцию элементов, выглядит так:

Map> items = Arrays.stream(itemFilesDir.listFiles(File::isDirectory)) .map(File::getName) .collect(Collectors.toMap(s->s, this::retrieveBrandItems)); 

Источник

Stream to HashMap :

1. Using Collectors.toMap(keyMapper, valueMapper, mergeFunction)

  • First variant of Collectors.toMap() method accepts 3 input-arguments
    1. Key mapper – mapping function to produce keys
    2. Value mapper – mapping function to produce values
    3. Merge Function – this is used to resolve collisions between values associated with the same key
  • Above method helps to convert Stream into Map
  • For converting into HashMap, create HashMap object and pass above obtained Map as constructor-argument
  • Finally, print converted HashMap pairs to console

StreamToMapUsingCollectorsToMap.java

package net.bench.resources.stream.to.hashmap; import java.util.HashMap; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; public class StreamToMapUsingCollectorsToMap < public static void main(String[] args) < // 1. Stream of String tokens StreamnameStream = Stream.of( "Rajiv", "Anbu", "Santosh", "Abdul", "Lingaraj" ); // 2. convert Stream to Map Map map = nameStream .collect(Collectors.toMap( Function.identity(), // 1. actual String as KEY String::length, // 2. String length as their VALUE (key1, key2) -> key1) // 3. duplicate KEY resolver ); // 2.1 print to console System.out.println("1. Stream to Map conversion : \n\n" + map); // 3. convert Map to HashMap using inter-conversion constructor HashMap hMap = new HashMap<>(map); // 3.1 print to console System.out.println("\n\n2. Stream to HashMap conversion : \n\n" + hMap); > >

1. Stream to Map conversion : 2. Stream to HashMap conversion :

2. Using Collectors.toMap(keyMapper, valueMapper, mergeFunction, supplier)

  • This is the 2 nd variant of Collectors.toMap() method which accepts 4 input-arguments
    1. Key mapper – mapping function to produce keys
    2. Value mapper – mapping function to produce values
    3. Merge Function – this is used to resolve collisions between values associated with the same key
    4. Supplier – function which returns a new, empty Map into which the results will be inserted
  • Above method helps to convert Stream into HashMap, LinkedHashMap or TreeMap directly or whichever Supplier we pass as 4 th argument
  • In the below example, we are passing HashMap implementation class as method/constructor reference HashMap::new
  • Finally, print converted HashMap pairs to console

StreamToHashMapUsingCollectorsToMap.java

package net.bench.resources.stream.to.hashmap; import java.util.HashMap; import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; public class StreamToHashMapUsingCollectorsToMap < public static void main(String[] args) < // 1. Stream of String tokens StreamnameStream = Stream.of( "Rajiv", "Anbu", "Santosh", "Abdul", "Lingaraj" ); // 2. convert Stream to HashMap HashMap hMap = nameStream .collect(Collectors.toMap( Function.identity(), // 1. actual String as KEY String::length, // 2. String length as their VALUE (key1, key2) -> key1, // 3. duplicate KEY resolver HashMap::new // 4. implementation-class )); // 2.1 print to console System.out.println("Stream to HashMap conversion : \n\n" + hMap); > >

Stream to HashMap conversion :

References :

Источник

Collecting Stream Items into Map in Java

Learn to collect Stream items into Map using Collectors.toMap() and Collectors.groupingBy() methods using Java Stream APIs.

1. Collectors.toMap() for Unique Key-value Pairs

If the stream items have the unique map key field then we can use Collectors.toMap() to collect items to Map in Map format.

For example, we can collect a list of Employee objects to Map in where employee ids are unique fields and used as keys to the Map entries.

import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Collectors; public class Main < public static void main(String[] args) < ListemployeeList = new ArrayList<>(Arrays.asList( new Employee(1, "A", 100), new Employee(2, "A", 200), new Employee(3, "B", 300), new Employee(4, "B", 400), new Employee(5, "C", 500), new Employee(6, "C", 600))); Map employeesMap = employeeList.stream() .collect( Collectors.toMap(Employee::getId, Function.identity()) ); System.out.println(employeesMap); > >

2. Collectors.groupingBy() when Multiple Keys have Same Value

If the stream has items where Map keys are duplicate then we can use Collectors.groupingBy() to collect elements in Map> format. Here for each map key, we will store all elements in a List as the value.

For example, we can collect a list of Employee objects to map in where employee names may be duplicate fields for some stream elements. In such a case, all employees with the same name will be stored in a List, and the list will be stored as Map value field.

import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class Main < public static void main(String[] args) < ListemployeeList = new ArrayList<>(Arrays.asList( new Employee(1, "A", 100), new Employee(2, "A", 200), new Employee(3, "B", 300), new Employee(4, "B", 400), new Employee(5, "C", 500), new Employee(6, "C", 600))); Map employeesMap = employeeList.stream() .collect(Collectors.groupingBy(Employee::getName)); System.out.println(employeesMap); > >

It is very important to know beforehand if the Stream elements will have a distinct value for the map key field or not.

If map keys are duplicate and we use Collectors.toMap() method, we will get the IllegalStateException:

Exception in thread "main" java.lang.IllegalStateException: Duplicate key Employee [id=5, name=C, salary=500.0] at java.util.stream.Collectors.lambda$throwingMerger$106(Collectors.java:133) at java.util.stream.Collectors$$Lambda$3/149928006.apply(Unknown Source) at java.util.HashMap.merge(HashMap.java:1245)

Источник

Java stream collect to hashmap

Большинство операций класса Stream, которые модифицируют набор данных, возвращают этот набор в виде потока. Однако бывают ситуации, когда хотелось бы получить данные не в виде потока, а в виде обычной коллекции, например, ArrayList или HashSet. И для этого у класса Stream определен метод collect . Первая версия метода принимает в качестве параметра функцию преобразования к коллекции:

 R collect(Collector collector)

Параметр R представляет тип результата метода, параметр Т — тип элемента в потоке, а параметр А — тип промежуточных накапливаемых данных. В итоге параметр collector представляет функцию преобразования потока в коллекцию.

Эта функция представляет объект Collector, который определен в пакете java.util.stream. Мы можем написать свою реализацию функции, однако Java уже предоставляет ряд встроенных функций, определенных в классе Collectors :

  • toList() : преобразование к типу List
  • toSet() : преобразование к типу Set
  • toMap() : преобразование к типу Map

Например, преобразуем набор в потоке в список:

import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.stream.Collectors; public class Program < public static void main(String[] args) < Listphones = new ArrayList(); Collections.addAll(phones, "iPhone 8", "HTC U12", "Huawei Nexus 6P", "Samsung Galaxy S9", "LG G6", "Xiaomi MI6", "ASUS Zenfone 2", "Sony Xperia Z5", "Meizu Pro 6", "Lenovo S850"); List filteredPhones = phones.stream() .filter(s->s.length() <10) .collect(Collectors.toList()); for(String s : filteredPhones)< System.out.println(s); >> >

Использование метода toSet() аналогично.

Set filteredPhones = phones.stream() .filter(s->s.length()<10) .collect(Collectors.toSet());

Для применения метода toMap() надо задать ключ и значение. Например, пусть у нас есть следующая модель:

class Phone < private String name; private int price; public Phone(String name, int price)< this.name=name; this.price=price; >public String getName() < return name; >public int getPrice() < return price; >>

Теперь применим метод toMap() :

import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; public class Program < public static void main(String[] args) < StreamphoneStream = Stream.of(new Phone("iPhone 8", 54000), new Phone("Nokia 9", 45000), new Phone("Samsung Galaxy S9", 40000), new Phone("LG G6", 32000)); Map phones = phoneStream .collect(Collectors.toMap(p->p.getName(), t->t.getPrice())); phones.forEach((k,v)->System.out.println(k + " " + v)); > > class Phone < private String name; private int price; public Phone(String name, int price)< this.name=name; this.price=price; >public String getName() < return name; >public int getPrice() < return price; >>

Лямбда-выражение p->p.getName() получает значение для ключа элемента, а t->t.getPrice() - извлекает значение элемента.

Если нам надо создать какой-то определенный тип коллекции, например, HashSet, то мы можем использовать специальные функции, которые определены в классах-коллекций. Например, получим объект HashSet:

import java.util.HashSet; import java.util.stream.Collectors; import java.util.stream.Stream; public class Program < public static void main(String[] args) < Streamphones = Stream.of("iPhone 8", "HTC U12", "Huawei Nexus 6P", "Samsung Galaxy S9", "LG G6", "Xiaomi MI6", "ASUS Zenfone 2", "Sony Xperia Z5", "Meizu Pro 6", "Lenovo S850"); HashSet filteredPhones = phones.filter(s->s.length()<12). collect(Collectors.toCollection(HashSet::new)); filteredPhones.forEach(s->System.out.println(s)); > >

Выражение HashSet::new представляет функцию создания коллекции. Аналогичным образом можно получать другие коллекции, например, ArrayList:

ArrayList result = phones.collect(Collectors.toCollection(ArrayList::new));

Вторая форма метода collect имеет три параметра:

 R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
  • supplier : создает объект коллекции
  • accumulator : добавляет элемент в коллекцию
  • combiner : бинарная функция, которая объединяет два объекта

Применим эту версию метода collect:

import java.util.ArrayList; import java.util.stream.Collectors; import java.util.stream.Stream; public class Program < public static void main(String[] args) < Streamphones = Stream.of("iPhone 8", "HTC U12", "Huawei Nexus 6P", "Samsung Galaxy S9", "LG G6", "Xiaomi MI6", "ASUS Zenfone 2", "Sony Xperia Z5", "Meizu Pro 6", "Lenovo S850"); ArrayList filteredPhones = phones.filter(s->s.length()<12) .collect( ()->new ArrayList(), // создаем ArrayList (list, item)->list.add(item), // добавляем в список элемент (list1, list2)-> list1.addAll(list2)); // добавляем в список другой список filteredPhones.forEach(s->System.out.println(s)); > >

Источник

Читайте также:  Msp midural ru obrashcheniya grajdan e priemnaya html
Оцените статью