Simple case without duplicate keys
Stream<String> characters = Stream.of("A", "B", "C"); Map<Integer, String> map = characters .collect(Collectors.toMap(element -> element.hashCode(), element -> element)); // map = {65=A, 66=B, 67=C}
To make things more declarative, we can use static method in Function interface - Function.identity(). We can replace this lambda element -> element with Function.identity().
Case where there might be duplicate keys
The javadoc for Collectors.toMap states:
Stream<String> characters = Stream.of("A", "B", "B", "C"); Map<Integer, String> map = characters .collect(Collectors.toMap( element -> element.hashCode(), element -> element, (existingVal, newVal) -> (existingVal + newVal))); // map = {65=A, 66=BB, 67=C}
The BinaryOperator passed to Collectors.toMap(...) generates the value to be stored in the case of a collision. It can
Grouping by value
You can use Collectors.groupingBy when you need to perform the equivalent of a database cascaded "group by" operation. To illustrate, the following creates a map in which people's names are mapped to surnames:
import java.util.*; import java.util.stream.*; import static java.util.stream.Collectors.*; class Person { final String name, surname; public Person(String n, String s){ this.name = n; this.surname = s; } public String getName(){ return name; } public String getSurname(){ return surname; } } class Sample{ public static void main(String[] args) { List<Person> people = Arrays.asList( new Person("Sam", "Rossi"), new Person("Sam", "Verdi"), new Person("John", "Bianchi"), new Person("John", "Rossi"), new Person("John", "Verdi") ); Map<String, List<String>> map = people.stream() .collect( // function mapping input elements to keys groupingBy(Person::getName, // function mapping input elements to values, // how to store values mapping(Person::getSurname, toList())) ); System.out.println(map); } }
A use case that comes across frequently, is creating a String from a stream, where the stream-items are separated by a certain character. The Collectors.joining() method can be used for this, like in the following example:
Stream<String> fruitStream = Stream.of("apple", "banana", "pear", "kiwi", "orange"); String result = fruitStream.filter(s -> s.contains("a")) .map(String::toUpperCase) .sorted() .collect(Collectors.joining(", ")); System.out.println(result);
Output:
APPLE, BANANA, ORANGE, PEAR
The Collectors.joining() method can also cater for pre- and postfixes:
String result = fruitStream.filter(s -> s.contains("e")) .map(String::toUpperCase) .sorted() .collect(Collectors.joining(", ", "Fruits: ", ".")); System.out.println(result);
Output:
Fruits: APPLE, ORANGE, PEAR.
List<String> data = new ArrayList<>(); data.add("Sydney"); data.add("London"); data.add("New York"); data.add("Amsterdam"); data.add("Mumbai"); data.add("California"); System.out.println(data); List<String> sortedData = data.stream().sorted().collect(Collectors.toList()); System.out.println(sortedData);
Output:
[Sydney, London, New York, Amsterdam, Mumbai, California] [Amsterdam, California, London, Mumbai, New York, Sydney]
It's also possible to use different comparison mechanism as there is a overloaded sorted version which takes a comparator as its argument.
Also, you can use a lambda expression for sorting:
List<String> sortedData2 = data.stream().sorted((s1,s2) -> s2.compareTo(s1)).collect(Collectors.toList());
This would output
[Sydney, New York, Mumbai, London, California, Amsterdam]
You can use Comparator.reverseOrder() to have a comparator that imposes the reverse of the natural ordering.
List<String> reverseSortedData = data.stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList());
Learn All in Tamil © Designed & Developed By Tutor Joes | Privacy Policy | Terms & Conditions