How to Use Java Streams
Hello everyone, in this article we are going to talk about Java Streams. We will see the frequently used methods of Java Streams and we will perform some operations.Let's get started.
Firstly what is stream in Java
Java streams provide pipelines to perform some operations using collections as data source. We can perform various operations over Collections which are similar to sql queries. We can perform filtering, controlling, mapping, ...etc. Stream does not change the source collection and we can create new collections after related operation is completed.
Now let's start the examples of these pipelines.
Firstly I want to state below collection definitions is going to be used in all examples.
static List<String> strs;
static List<Integer> ints;
public static void initializeStreams()
{
//We can initialize List with Arrays.asList method with using an array
strs = Arrays.asList("Burak", "Hamdi", "TUFAN");
Integer[] nums = new Integer[] {1, 2, 3, 4, 5};
ints = Arrays.asList(nums);
}
Now let's start to make some examples for better understanding.
forEach :
We can traverse all elements in a stream with forEach function. We can call function statically, element will be parameter of that function, we can call the inline function with lambda operator we can declare the anonymous function with the element
public static void forEachExamples() {
initializeStreams();
strs.stream().forEach(System.out::println);
strs.stream().forEach(s -> System.out.println(s));
ints.stream().forEach(i -> {
System.out.println(i);
});
}
Output will be
Burak
Hamdi
TUFAN
Burak
Hamdi
TUFAN
1
2
3
4
5
map :
map function of stream creates a new list with processing all elements of given stream. We need to declare a new List for return stream of map function. Map function protects the source array. It does not change the source. it creates new stream, we can declare the function as inline or a anonymous function.
public static void mapExample() {
initializeStreams();
List<Integer> mapped1 = ints.stream().map(n -> n * n).collect(Collectors.toList());
List<String> mappedReversed = strs.stream().map(s -> {
StringBuilder sb = new StringBuilder(s);
return sb.reverse().toString();
}).collect(Collectors.toList());
System.out.println(mapped1.toString());
System.out.println(mappedReversed.toString());
}
Program output will be
[1, 4, 9, 16, 25]
[karuB, idmaH, NAFUT]
filter :
filter function traverse all elements in given stream and check them according to a condition, we can create a new stream with only obeys the specified condition, we can define lambda function and also create an anonymous function, inner function of filter pipeline must return boolean result. Also we can directly get the number of element which passes the test.
public static void filterExample() {
initializeStreams();
List<String> filtered = strs.stream().filter( s -> s.contains("u")).collect(Collectors.toList());
List<Integer> customCondition = ints.stream().filter(i -> {
if(i * (i-1) > 10) return true;
else return false;
}).toList();
long evenNumbers = ints.stream().filter(n -> n % 2 == 0).count();
System.out.println(filtered.toString());
System.out.println(customCondition.toString());
System.out.println("Even numbers : " + evenNumbers);
}
Program output will be
[Burak]
[4, 5]
Even numbers : 2
sorted :
Sorted function will sort the stream as ascending order. We can also use a custom comparator for ordering the elements
public static void sortedExample() {
Integer[] unorderedNumbers = new Integer[] {5,99,3,66,4,88,2,6,7,1,6,1,0,2,0,8,74,62,23,8,14,36,58,41,23,95};
List<Integer> numbers = Arrays.asList(unorderedNumbers);
List<Integer> ordered = numbers.stream().sorted().toList();
List<Integer> descending = numbers.stream().sorted(new Comparator<Integer>() {
@Override
public int compare(Integer n1, Integer n2) {
return n1 > n2 ? -1 : 1;
}
}).toList();
System.out.println(ordered.toString());
System.out.println(descending.toString());
}
Program Output will be
[0, 0, 1, 1, 2, 2, 3, 4, 5, 6, 6, 7, 8, 8, 14, 23, 23, 36, 41, 58, 62, 66, 74, 88, 95, 99]
[99, 95, 88, 74, 66, 62, 58, 41, 36, 23, 23, 14, 8, 8, 7, 6, 6, 5, 4, 3, 2, 2, 1, 1, 0, 0]
reduce :
We can use all datas in a stream to create one single result.
public static void reduceExample() {
initializeStreams();
int sum = ints.stream().reduce(0, (res, n) -> res += n).intValue();
System.out.println(sum);
}
Program output will be
15
collector :
We can collect the result of the stream function. We can combine them into a string or push them into a List. We can convert data to a Set or a List. We can create a data stream as format as required.
public static void collectorsExample() {
Integer[] nums = new Integer[] {-3, -2, -1, 0, 1, 2, 3, 4};
List<Integer> numList = Arrays.asList(nums);
Set<Integer> _set = Arrays.asList(nums).stream().map(n -> n*n).collect(Collectors.toSet());
String _str = numList.stream().map(s -> s.toString()).collect(Collectors.joining(", "));
System.out.println(_set.toString());
System.out.println(_str);
}
Program Output will be
[0, 16, 1, 4, 9]
-3, -2, -1, 0, 1, 2, 3, 4
paralelStreaming :
Parallel streaming is a way to use multi cores of device. operations are performing at all cores of CPU, normal stream is performing on the single cores of computer so it is low performance but in parallelStream we will have high performance.
parallelStream does not care about order of elements but stream care about elements. if element order is not important we can use paralelStream. printing order will be changed at every execution. but performance will be increased.
all methods of stream and parallelStream are same. so we can switch quickly.
public static void parallelStreamExample() {
initializeStreams();
ints.parallelStream().forEach(i -> System.out.println(i));
}
Program outpt will be like, it may be changed according to device processor cores.
3
5
1
4
2
That is all in this article.
You can reach the example code file on Github via : https://github.com/thecodeprogram/TheSingleFiles/blob/master/JavaStreams.java
Have a nice streaming.
Burak Hamdi TUFAN
Comments