Introduction to Java Stream API
- 5 minutes read - 939 wordsPrior to JDK 8, collections
can only be managed through iterators
with the use of for
, foreach
or while
loops. It means that we instruct a computer to execute the algorithm steps.
int sum(List<Integer> list) {
Iterator<Integer> intIterator = list.iterator();
int sum = 0;
while (intIterator.hasNext()) {
int number = intIterator.next();
if (number > 5) {
sum += number;
}
}
return sum;
}
The above approach has the following tailbacks:
- We need to express how the iteration will take place, we needed an external iteration as the client program to handle the traversal.
- The program is sequential; no way to do it in parallel.
- The code is verbose.
Java 8 - Stream APIs
Java 8 introduces Stream API to circumvent the aforementioned shortcomings. It allows us to leverage other changes, e.g., lambda expression, method reference, functional interface and internal iteration introduced via forEach()
method.
The above logic of the program can be rewritten in a single line:
int sum(List<Integer> list) {
return list.stream().filter(i -> i > 5).mapToInt(i -> i).sum();
}
- The
streamed
content is filtered with the filter method, which takes apredicate
as its argument. - The
filter
method returns a new instance ofStream<T>
. - The
map
function is used to transform each element of the stream into a new element. The map returns aStream<R>
, in the above example, we usedmapToInt
to get theIntStream
. - Finally,
IntStream
has a sum operator, which calculates the sum of all elements in the stream, and we got the expected result so cleanly.
Sample Examples:
public class Java8Streams{
public static void main(String args[]) {
List<String> strList = Arrays.asList("java", "", "j2ee", "", "spring", "hibernate", "webservices");
// Count number of String which starts with "j"
long count = strList.stream().filter(x -> x.startsWith("j")).count();
System.out.printf("List %s has %d strings which startsWith 'j' %n", strList, count);
// Count String with length more than 4
count = strList.stream().filter(x -> x.length()> 4).count();
System.out.printf("List %s has %d strings of length more than 4 %n", strList, count);
// Count the empty strings
count = strList.stream().filter(x -> x.isEmpty()).count();
System.out.printf("List %s has %d empty strings %n", strList, count);
// Remove all empty Strings from List
List<String> emptyStrings = strList.stream().filter(x -> !x.isEmpty()).collect(Collectors.toList());
System.out.printf("Original List : %s, List without Empty Strings : %s %n", strList, emptyStrings);
// Create a List with String more than 4 characters
List<String> lstFilteredString = strList.stream().filter(x -> x.length()> 4).collect(Collectors.toList());
System.out.printf("Original List : %s, filtered list with more than 4 chars: %s %n", strList, lstFilteredString);
// Convert String to Uppercase and join them using comma
List<String> SAARC = Arrays.asList("India", "Japan", "China", "Bangladesh", "Nepal", "Bhutan");
String SAARCCountries = SAARC.stream().map(x -> x.toUpperCase()).collect(Collectors.joining(", "));
System.out.println("SAARC Countries: "+SAARCCountries);
// Create List of square of all distinct numbers
List<Integer> numbers = Arrays.asList(1, 3, 5, 7, 3, 6);
List<Integer> distinct = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
System.out.printf("Original List : %s, Square Without duplicates : %s %n", numbers, distinct);
//Get count, min, max, sum, and average for numbers
List<Integer> lstPrimes = Arrays.asList(3, 5, 7, 11, 13, 17, 19, 21, 23);
IntSummaryStatistics stats = lstPrimes.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Highest prime number in List : " + stats.getMax());
System.out.println("Lowest prime number in List : " + stats.getMin());
System.out.println("Sum of all prime numbers : " + stats.getSum());
System.out.println("Average of all prime numbers : " + stats.getAverage());
}
}
List [java, , j2ee, , spring, hibernate, webservices] has 2 strings which startsWith 'j'
List [java, , j2ee, , spring, hibernate, webservices] has 3 strings of length more than 4
List [java, , j2ee, , spring, hibernate, webservices] has 2 empty strings
Original List : [java, , j2ee, , spring, hibernate, webservices], List without Empty Strings : [java, j2ee, spring, hibernate, webservices]
Original List : [java, , j2ee, , spring, hibernate, webservices], filtered list with more than 4 chars: [spring, hibernate, webservices]
SAARC Countries: INDIA, JAPAN, CHINA, BANGLADESH, NEPAL, BHUTAN
Original List : [1, 3, 5, 7, 3, 6], Square Without duplicates : [1, 9, 25, 49, 36]
Highest prime number in List: 23
Lowest prime number in List: 3
Sum of all prime numbers: 119
Average of all prime numbers: 13.222222222222221
API overview
The main type in the JDK 8 Stream API package java.util.stream
is the Stream
interface. The types IntStream
, LongStream
, and DoubleStream
are streams over objects and the primitive int
, long
and double
types.
Differences between Stream
and Collection
:
- A stream does not store data.
- An operation on a stream does not modify its source, but simply produces a result.
- Collections have a finite size, but streams do not.
- Like an Iterator, a new stream must be generated to revisit the same elements of the source.
We can obtain Streams in the following ways:
- From a Collection via the
stream()
andparallelStream()
methods; - From an array via
Arrays.stream(Object[])
; - From static factory methods on the stream classes, such as
Stream.of(Object[])
,IntStream.range(int, int)
orStream.iterate(Object, UnaryOperator)
; - The lines of a file from
BufferedReader.lines()
; - Streams of file paths from methods in
Files
; - Streams of random numbers from
Random.ints()
; - Other stream-bearing methods:
BitSet.stream()
,Pattern.splitAsStream(java.lang.CharSequence)
, andJarFile.stream()
.
Stream operations
Intermediate operations
Stateless operations, such as filter and map, retain no state from previous element.
Stateful operations, such as distinct and sorted, may have state from the previous elements.
Terminal operations
Operations, such as Stream.forEach
or IntStream.sum
, may traverse the stream to produce a result or a side-effect. After the terminal operation is performed, the stream pipeline is considered consumed, and can no longer be used.
Reduction Operations
The general reduction operations are reduce()
and collect()
and the special reduction operations are sum()
, max()
, or count()
.
Parallelism
All the operations of streams can execute either in serial or in parallel. For example, Collection has methods Collection.stream()
and Collection.parallelStream()
, which produce sequential and parallel streams respectively.
References • https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
#stream-api #java 8 #java #whatsnew #introduction #tutorial #language #technology