Question of the Week #48
What are Streams (from java.util.stream) and how can they process data?
5 messages · Page 1 of 1 (latest)
What are Streams (from java.util.stream) and how can they process data?
Streams allow processing data in a declarative way.
A Stream represents a pipeline that starts at a source specifying where the data is coming from and ends with a terminal operation that collects (some of) the data or performs operations on it.
Streams utilize method chaining to chain together operations starting from the sink and ending at the terminal operation with an arbitrary amount of intermediate operations in between.
It is possible to get a Stream from any Collection by calling Collection#stream. Similarly, it is possible to get a Stream from an array using Arrays.stream:
List<String> someList = List.of("Hello", "World");
Stream<String> listStream = someList.stream();
String[] someArray = new String[]{"Hello", "World"};
Stream<String> listStream = Arrays.stream(someArray);
Common terminal operations include toList which gets a List with all elements of the Stream or collect which allows collecting the elements with a custom Collector.
List<String> streamConvertedToList = List.of("Hello", "World").stream().toList();//get a list back from the stream
Map<Character, List<String>> groupedByFirstCharacter = List.of("Hello", "World").stream().collect(Collectors.groupingBy(str -> str.charAt(0)));//{H=[Hello], W=[World]}
Similarly, it is possible to use finyAny/findFirst which get a single element from the Stream wrapped in an Optional or Optional.empty() if there are no such elements:
List<String> someList = List.of("Hello", "World");
Optional<String> someElement = someList.stream().findAny();
Between the source and the terminal operations, it is possible to add intermediate operations. For example, filter can be used to only include elements matching a condition:
List<String> streamConvertedToList = List.of("Hello", "World")
.stream()
.filter(str -> str.startsWith("H"))//ignore elements not starting with H
.toList();//List containing Hello
Another common intermediate operations is map which transforms all object using a function:
List<Integer> lengths = List.of("Hello", "World")
.stream()
.map(str -> str.length())//convert all Strings to their lengths
.toList();//5, 5
Similar to that, the method flatMap accepts a function that converts each object to a Stream and allows processing all elements of all streams returned by the function.
List.of("Hello", "World")
.stream()
.flatMap(str -> str.chars().boxed())//chars().boxed() returns a Stream containing all chars of the String as Integer objects
.toList();//list of all characters/code points in the original Strings: [72, 101, 108, 108, 111, 87, 111, 114, 108, 100]
The stream package provides a variety of things, the Stream API's work is to process complex data and to sum it up the data can be processed sequentially or parallely, there are more ways to process the data.
some key features are stream() this returns the source or collection or an array, and also i/o channels but we won't cover that
and then there's parallelStream() to process parallely, the Stream API would also give us access to mappings, filtering and more of it's methods.