How to Use Java Streams

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.

In this article we are going to talk about below pipelines of streams :
  • forEach : We can traverse all elements of a collection with foreach. We can declare an inline function and anonymous function inside foreach pipeline.
  • map : We can create a new collection with using all elements of a collection. It does not change the original collection, it creates new one. We can declare inline or anonymous function inside map pipeline.
  • filter : We can traverse all elements and control them for a condition. Used function returns boolean according to condition. All true returned elements are being collected in a new collection.
  • sorted : We can sort the data in ascending order. Also we can use a custom comparator in sorted pipeline.
  • reduce : We can create a value with using all element values in a collection. We can also send an initial value for the calculation.
  • collector : We can create the format of collected data. We can create our output as various data formats. We can create a String output, set output, list output, etc...
  • paralelStreaming : We can perform the stream operations with using all avail core of device asynchoronously. It will increase the performance but does not care about order of the elements.
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&lt;Integer&gt; mapped1 = ints.stream().map(n -&gt; n * n).collect(Collectors.toList());
		List&lt;String&gt; mappedReversed = strs.stream().map(s -&gt; { 
			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


Tags


Share this Post

Send with Whatsapp

Post a Comment

Success! Your comment sent to post. It will be showed after confirmation.
Error! There was an error sending your comment.

Comments

  • There is no comment. Be the owner of first comment...