215

I have just discovered the new Java 8 stream capabilities. Coming from Python, I was wondering if there was now a neat way to do operations on arrays like summing, multiplying two arrays in a "one line pythonic" way ?

Thanks

Anton Sorokin
  • 494
  • 6
  • 23
BlackLabrador
  • 2,829
  • 5
  • 18
  • 21

4 Answers4

317

There are new methods added to java.util.Arrays to convert an array into a Java 8 stream which can then be used for summing etc.

int sum =  Arrays.stream(myIntArray).sum();

Multiplying two arrays is a little more difficult because I can't think of a way to get the value AND the index at the same time as a Stream operation. This means you probably have to stream over the indexes of the array.

//in this example a[] and b[] are same length
int[] a = ...
int[] b = ...
 
int[] result = new int[a.length];

IntStream.range(0, a.length).forEach(i -> result[i] = a[i] * b[i]);

Commenter @Holger points out you can use the map method instead of forEach like this:

int[] result = IntStream.range(0, a.length).map(i -> a[i] * b[i]).toArray();
Community
  • 1
  • 1
dkatzel
  • 31,188
  • 3
  • 63
  • 67
  • 17
    `int[] result=IntStream.range(0, a.length).map( i->a[i]* b[i]).toArray();` – Holger Jun 24 '14 at 16:33
  • 2
    @Holger yes that would work too. Although you probably want to use `mapToInt` to avoid boxing. – dkatzel Jun 24 '14 at 16:43
  • That last amounts to a simulation of zip where you must preallocate storage for the result. I wonder why there is no zip in the Streams library? – Reb.Cabin Aug 20 '15 at 15:19
  • According to [this SO answer](http://stackoverflow.com/questions/17640754/zipping-streams-using-jdk8-with-lambda-java-util-stream-streams-zip#23529010), a zip was in an earlier beta of Java 8, then taken out. Luckily the poster had the source and it is in the answer. I have used the code several times and it seems to work very well. – sparc_spread May 03 '16 at 17:29
  • 2
    @dkatzel — Since it's already an IntStream, "map" takes a IntUnaryOperator, so there is no boxing involved. – M. Justin Feb 15 '17 at 02:12
61

You can turn an array into a stream by using Arrays.stream():

int[] ns = new int[] {1,2,3,4,5};
Arrays.stream(ns);

Once you've got your stream, you can use any of the methods described in the documentation, like sum() or whatever. You can map or filter like in Python by calling the relevant stream methods with a Lambda function:

Arrays.stream(ns).map(n -> n * 2);
Arrays.stream(ns).filter(n -> n % 4 == 0);

Once you're done modifying your stream, you then call toArray() to convert it back into an array to use elsewhere:

int[] ns = new int[] {1,2,3,4,5};
int[] ms = Arrays.stream(ns).map(n -> n * 2).filter(n -> n % 4 == 0).toArray();
Ian Knight
  • 2,356
  • 2
  • 18
  • 22
10

Be careful if you have to deal with large numbers.

int[] arr = new int[]{Integer.MIN_VALUE, Integer.MIN_VALUE};
long sum = Arrays.stream(arr).sum(); // Wrong: sum == 0

The sum above is not 2 * Integer.MIN_VALUE. You need to do this in this case.

long sum = Arrays.stream(arr).mapToLong(Long::valueOf).sum(); // Correct
Sanghyun Lee
  • 21,644
  • 19
  • 100
  • 126
5

Please note that Arrays.stream(arr) create a LongStream (or IntStream, ...) instead of Stream so the map function cannot be used to modify the type. This is why .mapToLong, mapToObject, ... functions are provided.

Take a look at why-cant-i-map-integers-to-strings-when-streaming-from-an-array

Rafael
  • 2,521
  • 2
  • 33
  • 59