Для конкретного питання створення реверсу IntStream
спробуйте щось подібне:
static IntStream revRange(int from, int to) {
return IntStream.range(from, to)
.map(i -> to - i + from - 1);
}
Це дозволяє уникнути боксу та сортування.
Що стосується загального питання про те, як повернути потік будь-якого типу, я не знаю, чи існує "належний" спосіб. Є кілька способів, які я можу придумати. Обидва закінчують зберігання елементів потоку. Я не знаю способу повернути потік без збереження елементів.
Цей перший спосіб зберігає елементи в масив і зчитує їх у потоці у зворотному порядку. Зауважте, що оскільки ми не знаємо тип виконання елементів потоку, ми не можемо набрати масив належним чином, вимагаючи неперевіреного складу.
@SuppressWarnings("unchecked")
static <T> Stream<T> reverse(Stream<T> input) {
Object[] temp = input.toArray();
return (Stream<T>) IntStream.range(0, temp.length)
.mapToObj(i -> temp[temp.length - i - 1]);
}
Інша методика використовує колектори для накопичення предметів у зворотному списку. Це робить багато вставок на передній частині ArrayList
об’єктів, тому багато копіювання триває.
Stream<T> input = ... ;
List<T> output =
input.collect(ArrayList::new,
(list, e) -> list.add(0, e),
(list1, list2) -> list1.addAll(0, list2));
Можливо, можливо написати набагато ефективніший колектор зворотного ходу за допомогою якоїсь спеціальної структури даних.
ОНОВЛЕННЯ 2016-01-29
Оскільки це питання останнім часом привернуло трохи уваги, я думаю, що я повинен оновити свою відповідь, щоб вирішити проблему із вставкою в передній частині ArrayList
. Це буде жахливо неефективно з великою кількістю елементів, що вимагає копіювання O (N ^ 2).
Переважно використовувати ArrayDeque
замість цього, який ефективно підтримує вставку спереду. Невелика зморшка полягає в тому, що ми не можемо використовувати форму три аргументу Stream.collect()
; він вимагає, щоб вміст другого аргументу було об'єднано в перший аргумент, і немає жодної операції "додавання всіх на передній" Deque
. Натомість ми використовуємо addAll()
для додавання вмісту першого аргументу до кінця другого, а потім повертаємо другий. Для цього потрібно використовувати Collector.of()
заводський метод.
Повний код такий:
Deque<String> output =
input.collect(Collector.of(
ArrayDeque::new,
(deq, t) -> deq.addFirst(t),
(d1, d2) -> { d2.addAll(d1); return d2; }));
Результат - це Deque
замість List
, але це не повинно бути великою проблемою, оскільки його можна легко повторити чи передавати в поточному порядку.
IntStream
немає.sorted(Comparator)
; вам доведеться пройтиStream<Integer>
перший і назад там, перш ніжIntStream