Получение списка из java.util.stream.Stream в Java 8

collections lambda java-8 java-stream

285204 просмотра

12 ответа

2566 Репутация автора

Я играл с лямбдами Java 8, чтобы легко фильтровать коллекции. Но я не нашел краткий способ получить результат в виде нового списка в том же утверждении. Вот мой самый лаконичный подход:

List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = new ArrayList<>();
sourceLongList.stream().filter(l -> l > 100).forEach(targetLongList::add);

Примеры в сети не ответили на мой вопрос, потому что они останавливаются без создания нового списка результатов. Должен быть более лаконичный способ. Я бы ожидал, что Streamкласс имеет методы , как toList(), toSet()...

Есть ли способ, которым переменные targetLongListмогут быть непосредственно назначены третьей строкой?

Автор: Daniel K. Источник Размещён: 12.02.2013 10:26

Ответы (12)


562 плюса

8613 Репутация автора

Решение

То, что вы делаете, может быть самым простым способом, при условии, что ваш поток остается последовательным - в противном случае вам придется предварительно вызвать вызов sequential () forEach.

[позднее редактирование: причина, по которой вызов sequential () необходим, заключается в том, что код в том виде, в котором он стоит ( forEach(targetLongList::add)), был бы нечетким, если бы поток был параллельным. Даже в этом случае не будет достигнут ожидаемый эффект, поскольку forEachон явно недетерминирован - даже в последовательном потоке порядок обработки элементов не гарантируется. Вы должны использовать forEachOrderedдля обеспечения правильного заказа. Целью разработчиков Stream API является то, что вы будете использовать коллектор в этой ситуации, как показано ниже.]

Альтернатива

targetLongList = sourceLongList.stream()
    .filter(l -> l > 100)
    .collect(Collectors.toList());
Автор: Maurice Naftalin Размещён: 12.02.2013 12:22

162 плюса

3967 Репутация автора

Другой подход заключается в использовании Collectors.toCollection:

targetLongList = 
    sourceLongList.stream().
    filter(l -> l > 100).
    collect(Collectors.toCollection(ArrayList::new));
Автор: MohamedSanaulla Размещён: 17.03.2013 06:28

0 плюса

7819 Репутация автора

Если кто-то (например, я) ищет способы борьбы с объектами вместо примитивных типов, тогда используйте mapToObj()

String ss = "An alternative way is to insert the following VM option before "
        + "the -vmargs option in the Eclipse shortcut properties(edit the "
        + "field Target inside the Shortcut tab):";

List<Character> ll = ss
                        .chars()
                        .mapToObj(c -> new Character((char) c))
                        .collect(Collectors.toList());

System.out.println("List type: " + ll.getClass());
System.out.println("Elem type: " + ll.get(0).getClass());
ll.stream().limit(50).forEach(System.out::print);

печатает:

List type: class java.util.ArrayList
Elem type: class java.lang.Character
An alternative way is to insert the following VM o
Автор: Kashyap Размещён: 02.10.2015 03:42

11 плюса

6997 Репутация автора

Мне нравится использовать метод util, который возвращает коллектор, ArrayListкогда это то, что я хочу.

Я думаю, что использование решения Collectors.toCollection(ArrayList::new)немного слишком шумно для такой обычной операции.

Пример:

ArrayList<Long> result = sourceLongList.stream()
    .filter(l -> l > 100)
    .collect(toArrayList());

public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
    return Collectors.toCollection(ArrayList::new);
}

Этим ответом я также хочу продемонстрировать, насколько просто создавать и использовать пользовательские коллекторы, что в целом очень полезно.

Автор: Lii Размещён: 20.11.2015 09:15

1 плюс

3729 Репутация автора

Если вы не возражаете против использования сторонних библиотек, в библиотеке AOL cyclops-реагировать (раскрытие которой я участвую) есть расширения для всех типов коллекций JDK , включая List . Интерфейс ListX расширяет java.util.List и добавляет большое количество полезных операторов, включая фильтр.

Вы можете просто написать

ListX<Long> sourceLongList = ListX.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
ListX<Long> targetLongList = sourceLongList.filter(l -> l > 100);

ListX также может быть создан из существующего списка (через ListX.fromIterable)

Автор: John McClean Размещён: 25.02.2016 10:18

4 плюса

1070 Репутация автора

Если у вас есть массив примитивов, вы можете использовать коллекции примитивов, доступные в Eclipse Collections .

LongList sourceLongList = LongLists.mutable.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
LongList targetLongList = sourceLongList.select(l -> l > 100);

Если вы не можете изменить sourceLongList с List:

List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = 
    ListAdapter.adapt(sourceLongList).select(l -> l > 100, new ArrayList<>());

Если вы хотите использовать LongStream:

long[] sourceLongs = new long[]{1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L};
LongList targetList = 
    LongStream.of(sourceLongs)
    .filter(l -> l > 100)
    .collect(LongArrayList::new, LongArrayList::add, LongArrayList::addAll);

Примечание: я участвую в коллекциях Eclipse.

Автор: Nikhil Nanivadekar Размещён: 27.03.2016 12:08

-2 плюса

271 Репутация автора

Если вы не используете parallel()это будет работать

List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);

List<Long> targetLongList =  new ArrayList<Long>();

sourceLongList.stream().peek(i->targetLongList.add(i)).collect(Collectors.toList());
Автор: Debapriya Biswas Размещён: 12.08.2016 07:04

4 плюса

5303 Репутация автора

Немного более эффективный способ (избегайте создания исходного списка и автоматической распаковки с помощью фильтра):

List<Long> targetLongList = LongStream.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L)
    .filter(l -> l > 100)
    .boxed()
    .collect(Collectors.toList());
Автор: msayag Размещён: 06.10.2016 07:13

0 плюса

948 Репутация автора

Вот код от AbacusUtil

LongStream.of(1, 10, 50, 80, 100, 120, 133, 333).filter(e -> e > 100).toList();

Раскрытие информации: я разработчик AbacusUtil.

Автор: user_3380739 Размещён: 02.12.2016 07:46

0 плюса

75 Репутация автора

String joined = 
                Stream.of(isRead?"read":"", isFlagged?"flagged":"", isActionRequired?"action":"", isHide?"hide":"")
                      .filter(s -> s != null && !s.isEmpty())
                      .collect(Collectors.joining(","));
Автор: sharath Размещён: 23.02.2017 10:54

3 плюса

125 Репутация автора

collect(Collectors.toList());

Это вызов, который вы можете использовать для преобразования любого потока в список.

Автор: Pramod Размещён: 18.09.2017 10:03

0 плюса

61 Репутация автора

Существует еще один вариант метода сбора данных, предоставляемый классом LongStream, а также классами IntStream и DoubleStream.

<R> R collect(Supplier<R> supplier,
              ObjLongConsumer<R> accumulator,
              BiConsumer<R,R> combiner)

Выполняет изменяемую операцию сокращения над элементами этого потока. Изменяемое сокращение - это такое, в котором уменьшенное значение представляет собой изменяемый контейнер результатов, такой как ArrayList, и элементы включаются путем обновления состояния результата, а не путем замены результата. Это дает результат, эквивалентный:

R result = supplier.get();
  for (long element : this stream)
       accumulator.accept(result, element);
  return result;

Как и Reduce (long, LongBinaryOperator), операции сбора могут быть распараллелены без дополнительной синхронизации. Это терминальная операция.

И ответ на ваш вопрос с этим методом сбора, как показано ниже:

    LongStream.of(1L, 2L, 3L, 3L).filter(i -> i > 2)
    .collect(ArrayList::new, (list, value) -> list.add(value)
    , (list1, list2) -> list1.addAll(list2));

Ниже приведен эталонный вариант метода, который довольно умен, но кое-что сложно понять:

     LongStream.of(1L, 2L, 3L, 3L).filter(i -> i > 2)
    .collect(ArrayList::new, List::add , List::addAll);

Ниже будет вариант HashSet:

     LongStream.of(1L, 2L, 3L, 3).filter(i -> i > 2)
     .collect(HashSet::new, HashSet::add, HashSet::addAll);

Аналогично вариант LinkedList выглядит так:

     LongStream.of(1L, 2L, 3L, 3L)
     .filter(i -> i > 2)
     .collect(LinkedList::new, LinkedList::add, LinkedList::addAll);
Автор: Vaneet Kataria Размещён: 25.01.2019 11:57
Вопросы из категории :
32x32