Коллекция для потоковой передачи в новую коллекцию

Я ищу самый бесплатный способ фильтрации коллекции. Я думаю что-то вроде

Collection<?> foo = existingCollection.stream().filter( ... ). ...

Но я не уверен, как лучше перейти от фильтра, к возврату или заполнению другой коллекции. Большинство примеров, похоже, похожи на "и здесь вы можете печатать". Возможно, существует конструктор или метод вывода, который мне не хватает.

Ответ 1

Это причина, по которой большинство примеров не позволяют сохранить результат в Collection. Это не рекомендуемый способ программирования. У вас уже есть Collection, тот, который предоставляет исходные данные и коллекции, бесполезен сам по себе. Вы хотите выполнить определенные операции над ним, поэтому идеальным вариантом является выполнение операции с использованием потока и пропуски хранения данных в промежуточной Collection. Это то, что большинство примеров пытаются предложить.

Конечно, есть много существующих API, работающих с Collection и всегда будет. Таким образом, Stream API предлагает различные способы удовлетворения спроса на Collection.

  • Получите произвольную реализацию List с результатом:

    List<T> results = l.stream().filter(…).collect(Collectors.toList());
    
  • Получите произвольную реализацию Set содержащую результат:

    Set<T> results = l.stream().filter(…).collect(Collectors.toSet());
    
  • Получите конкретную Collection:

    ArrayList<T> results =
      l.stream().filter(…).collect(Collectors.toCollection(ArrayList::new));
    
  • Добавить в существующую Collection:

    l.stream().filter(…).forEach(existing::add);
    
  • Создать массив:

    String[] array=l.stream().filter(…).toArray(String[]::new);
    
  • Используйте массив для создания списка с определенным конкретным поведением (изменяемый, фиксированный размер):

    List<String> al=Arrays.asList(l.stream().filter(…).toArray(String[]::new));
    
  • Разрешить параллельно способному потоку добавлять во временные локальные списки и присоединяться к ним потом:

    List<T> results
      = l.stream().filter(…).collect(ArrayList::new, List::add, List::addAll);
    

    (Примечание: это тесно связано с тем, как в настоящее время реализуется Collectors.toList(), но это подробности реализации, то есть нет гарантии, что будущие реализации toList() все равно возвратят ArrayList)

Ответ 2

Пример из java.util.stream документации:

List<String>results =
     stream.filter(s -> pattern.matcher(s).matches())
           .collect(Collectors.toList());

Collectors имеет метод toCollection(), я бы предложил посмотреть этот путь.

Ответ 3

В качестве примера, который больше соответствует стилю функционального программирования Java 8:

Collection<String> a = Collections.emptyList();
List<String> result = a.stream().
     filter(s -> s.length() > 0).
     collect(Collectors.toList());