concurrent

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:

  • http://www.javacodegeeks.com/2014/05/java-8-features-tutorial.html
  • http://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html
  • http://examples.javacodegeeks.com/core-java/util/concurrent/java-8-concurrency-tutorial/
  • http://examples.javacodegeeks.com/core-java/java-8-stream-api-tutorial/

    Download the code

    Download
    All examples from this article (and some more) can be downloaded in the following link: parallelArrays.
  • Dani Buiza

    Daniel Gutierrez Diez holds a Master in Computer Science Engineering from the University of Oviedo (Spain) and a Post Grade as Specialist in Foreign Trade from the UNED (Spain). Daniel has been working for different clients and companies in several Java projects as programmer, designer, trainer, consultant and technical lead.
    Subscribe
    Notify of
    guest

    This site uses Akismet to reduce spam. Learn how your comment data is processed.

    0 Comments
    Inline Feedbacks
    View all comments
    Back to top button