Java 8 Parallel Arrays Example
In this article we are going to talk about the new possibilities offered in Java 8 for execute Arrays
operations in parallel. We are going to focus on the Arrays
class methods.
At the end of this article you can download all the examples and snippets (and more). All code has been implemented using Java 8 update 11 and Eclipse Luna version 4.4.
The Arrays
class provides several functionalities for manipulating arrays, like sorting, searching and others. Since Java update 8 many of these features are also available in parallel mode, that is, it is possible to manipulate arrays in parallel for sorting, applying functions to all entries of the array (in combination with Java 8 Lambdas) or generating streams
that can be handled using thread safe and concurrent methods as well.
In this article we are going to see how to sort arrays in parallel using the method parallelSort()
, apply functions to all members of the array using the method parallelSetAll()
, how to use the parallelPrefix()
method and how to generate streams
and take advantage of all its features that support concurrency. If you are interested in learning more about streams
you can read the article .
parallel sorting
The Arrays
class offers the possibility to sort an array using different sort()
methods. Since Java update 8 it is also possible to sort arrays using sort methods that support concurrency.
In order to call this method we just need to pass the array that we want to sort as reference and it will be sorted:
Arrays.parallelSort( array );
You can provide an specific comparator if you want to perform the sorting based in other criteria. Here is an example of parallel sorting using a custom comparator (very simple in this case):
Comparator comparator = new Comparator() { @Override public int compare( String str1, String str2 ) { return str1.compareTo( str2 ); } }; Arrays.parallelSort( arrayStr, comparator );
You can do the same using Lambda expressions:
Arrays.parallelSort( arrayStr, ( x, y ) -> x.compareTo( y ) );
It is also possible to pass the range that we want to sort in the array:
Arrays.parallelSort( arrayStr, startIndex, endIndex, comparator );
Equivalents method exists in the Arrays
class without the prefix “parallel”. They do not support concurrency and are not thread safe.
Applying functions
Java 8 introduces the concept of functions or closures in Java, they are called Lambdas. It is possible to apply functions or Lambda expressions to all elements of an array by using the parallelSetAll()
(or setAll()
if you do not want to support parallelism):
IntToDoubleFunction functionToUse = new IntToDoubleFunction() { @Override public double applyAsDouble( int x ) { return x * 100; } }; Arrays.parallelSetAll( array, functionToUse );
The code shown above modifies all elements in the array by multiplying them per 100. This is done in parallel. It is also possible to use directly a Lambda expression as parameter:
Arrays.parallelSetAll( array, x -> x * 100 );
parallelPrefix method
There are cases where we would like to perform operations in each element of an array (or in a range of them) based on the previous value. This is possible by using the method parallelPrefix()
:
DoubleBinaryOperator binaryOperator = new DoubleBinaryOperator() { @Override public double applyAsDouble( double x, double y ) { return x + y; } }; // we can use binary operators as prefix in parallel Arrays.parallelPrefix( array, binaryOperator ); // also using lambdas Arrays.parallelPrefix( array, ( x, y ) -> x + y );
In the code above we can see that it is also possible to use Lambda expressions directly as parameter, as it was for the method parallelSetAll()
.
If we want to perform these operations only in a range of the array elements we can pass the start and end indexes and the operation will only be done between the range extremes:
int startIndex = 100; int endIndex = 150; Arrays.parallelPrefix( array, startIndex, endIndex, ( x, y ) -> x + y );
The method parallelPrefix()
is not that intuitive and, in my opinion, its name is confusing; so I am going to provide a very basic example that would help to understand a bit this method. If we have an array like the following one:
double[] array = {1.0, 2.0, 3.0};
And we want to apply to every entry a calculation based in the previous value, for example, if previous value is odd, we multiply the current entry by 2, otherwise leave the value as it is, so more or less we are going to multiply by 2 all entries which previous value is odd (I do not know why we would like to do this, but it is just an example). We can write something like the following (using Lambdas):
Arrays.parallelPrefix( array, ( x, y ) -> { if( x % 2 != 0 ) return y * 2; return y; } );
The result of printing out this array before and after the operation is done would be:
element at pos 0 previously 1.0 element at pos 1 previously 2.0 element at pos 2 previously 3.0 element at pos 0 after 1.0 element at pos 1 after 4.0 element at pos 2 after 3.0
We can see how the only entry that has been changed is the second one because its previous value is odd.
Streams from arrays
Although it is not directly related to concurrency using arrays, it is good to mention that since Java update 8 is possible to generate streams from arrays by using the stream()
methods:
// all streams functionalities are available DoubleStream streamFromArray = Arrays.stream( array );
The variable streamFromArray
exposes all possible functionalities and features that the Stream
class offers. Since streams
offer parallel processing as well, it has to be taken into consideration while handling arrays in parallel:
// also using parallel streams Arrays.stream( array ).filter( x -> x > 10 ).parallel().forEach( System.out::println );
The snippet above shows how to process all elements of an array in parallel by using streams. One important different to the methods shown before is that the array (or its elements) is not changed if using streams.
Summary
So that’s it!
We explained how to take advantage of parallelism while handling arrays in Java 8. There are several methods that support this, like parallelSort()
or parallelSetAll
and it is possible to generate streams
from arrays and use all their thread safe methods. It is also important to mention that if it is not wanted to manipulate arrays using concurrent methods, the Arrays
class offers also “non concurrent” counterparts like sort()
, setAll()
, etc.
Links
Here are some links that may be helpful while finding information about arrays, concurrency, streams or any other Java 8 features:
Download the code
All examples from this article (and some more) can be downloaded in the following link: parallelArrays.