Java 8 Stream и работа с массивами

Я только что открыл новые возможности потока Java 8. Исходя из Python, мне было интересно, есть ли теперь аккуратный способ делать операции над массивами, например, суммировать, умножая два массива на "одну линию pythonic"?

Спасибо

Ответ 1

В java.util.Arrays добавлены новые методы для преобразования массива в поток Java 8, который затем можно использовать для суммирования и т.д.

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

Умножение двух массивов немного сложнее, потому что я не могу придумать способ получить значение И индекс одновременно с операцией Stream. Это означает, что вам, вероятно, придется перетекать по индексам массива.

//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]);

ИЗМЕНИТЬ

Комментарий @Holger указывает, что вместо forEach можно использовать метод map:

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

Ответ 2

Вы можете превратить массив в поток с помощью Arrays.stream():

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

Как только вы получите свой поток, вы можете использовать любой из методов, описанных в документации, например sum() или что-то еще. Вы можете map или filter как в Python, вызвав соответствующие потоковые методы с помощью функции Lambda:

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

Как только вы закончите изменять свой поток, вы затем вызываете toArray(), чтобы преобразовать его обратно в массив для использования в другом месте:

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

Ответ 3

Будьте осторожны, если вам приходится иметь дело с большими числами.

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

Сумма выше не 2 * Integer.MIN_VALUE. Вы должны сделать это в этом случае.

long sum = Arrays.stream(arr).mapToLong(Long::valueOf).sum(); // Correct

Ответ 4

Обратите внимание, что Arrays.stream(arr) создает LongStream (или IntStream,...) вместо Stream, поэтому функция карты не может использоваться для изменения типа. Вот почему предоставляются функции .mapToLong, mapToObject,...

Взгляните на why-cant-i-map-integers-to-strings-when-streaming-from-an-array