У меня есть два целочисленных массива, например. -
int[] a = {2, 7, 9}
int[] b = {4, 2, 8}
Я хочу сравнить его поэлементно, то есть 2 с 4, затем 7 с 2 и, наконец, 9 с 8. Каждый результат сравнения будет сохранен в списке.
Это довольно легко сделать традиционными способами Java. Но я хочу использовать здесь Stream. Есть указатели?




Вы можете сделать это так,
List<Boolean> equalityResult = IntStream.range(0, a.length).mapToObj(i -> a[i] == b[i])
.collect(Collectors.toList());
Предварительное условие: оба массива имеют одинаковый размер.
Предполагая, что длина обоих входных массивов одинакова
List<Integer> list = IntStream.range(0, a.length).mapToObj(i -> Integer.compare(a[i], b[i]))
.collect(Collectors.toCollection(() -> new ArrayList<>(a.length)));
@PeterLawrey Спасибо за предложение, я тоже об этом подумал. Ждал, чтобы кто-нибудь просмотрел это и помог мне понять, может ли инициализация массива с емкостью, такой как в () -> new ArrayList<>(a.length), быть чем-то полезным, чем Supplier<List<T>>) ArrayList::new (возможно, емкость по умолчанию!) С этой реализацией сборщиков?
По емкости пока нет хорошего решения. Инициализация ArrayList с количеством ожидаемых элементов может быть хорошей для последовательного потока, но приведет к возникновению слишком больших временных массивов с параллельным потоком. Сегодня лучшим решением будет List<Integer> list = Arrays.asList( /* your stream operation */ .toArray(Integer[]::new));, поскольку он будет использовать известное количество элементов даже в параллельном случае, позволяя всем потокам записывать в один последний массив, когда размеры предсказуемы, как в этом конкретном случае. Но не пытайтесь оптимизировать, если нет проблем с производительностью.
То же, что и другие ответы, с небольшой разницей
List<Integer> result = IntStream.rangeClosed(0,a.length-1)
.boxed()
.map(i->Integer.compare(a[i],b[i]))
.collect(Collectors.toList());
Вы можете использовать .mapToObj вместо .boxed().map
И вы можете использовать range(0, a.length) вместо rangeClosed(0, a.length-1)
По сути, вы ищете функциональность операции Zip (которая пока недоступна в Java).
Чтобы получить в результате набор логических значений, я бы рекомендовал:
boolean[] accumulator = new boolean[a.length];
IntStream.range(0, a.length)
.forEachOrdered(i -> accumulator[i] = a[i] == b[i]);
и, соответственно, чтобы получить результат в виде int между соответствующими элементами в обоих массивах:
int[] ints = IntStream.range(0, a.length)
.map(i -> Integer.compare(a[i], b[i]))
.toArray();
Я не уверен, что forEachOrdered будет иметь значение в этом случае. c.f. для каждого
@PeterLawrey, я думаю, это вопрос предпочтений в данном конкретном случае. Так что да, вы правы, можно было просто использовать forEach.
Вы можете использовать
toList()вместоtoCollection(...)