我正在寻找最无痛的方式来过滤收藏品。我想像这样的东西
Collection<?> foo = existingCollection.stream().filter( ... ). ...
但是我不确定如何从过滤器转换为返回或填充另一个集合是最好的。大多数例子看起来像“在这里你可以打印”。可能我漏掉了一个构造函数或者输出方法。
作为一个更符合 Java8函数式编程风格的例子:
Collection<String> a = Collections.emptyList(); List<String> result = a.stream(). filter(s -> s.length() > 0). collect(Collectors.toList());
java.util.stream文档中的一个例子:
java.util.stream
List<String>results = stream.filter(s -> pattern.matcher(s).matches()) .collect(Collectors.toList());
Collectors有一个 toCollection()方法,我建议这样看。
Collectors
toCollection()
大多数示例避免将结果存储到 Collection中是有原因的。这不是推荐的编程方式。您已经有了一个 Collection,提供源数据和集合的 Collection本身没有任何用处。您希望对其执行某些操作,因此理想的情况是使用流执行操作,并跳过在中间 Collection中存储数据。这是大多数例子试图暗示的。
Collection
当然,有很多现有的 API 可以与 Collection一起工作,而且将来也会一直存在。因此,Stream API 提供了不同的方法来处理对 Collection的需求。
Stream
获取包含所有元素(JDK 16)的不可修改的 List实现:
List
List<T> results = l.stream().filter(…).toList();
获得一个任意的 List实现,其中包含结果:
List<T> results = l.stream().filter(…).collect(Collectors.toList());
获得一个像 List.of(…)(JDK 10)那样禁止 null的 无法修改的 List:
List.of(…)
null
List<T> results = l.stream().filter(…).collect(Collectors.toUnmodifiableList());
获得一个任意的 Set实现,其中包含结果:
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)
Collectors.toList()
toList()
ArrayList
您可能希望使用来自 Collectors类的 toList、 toSet或 toMap方法。
toList
toSet
toMap
然而,为了获得更多的控制权,可以使用 toCollection方法。下面是一个简单的例子:
toCollection
Collection<String> c1 = new ArrayList<>(); c1.add("aa"); c1.add("ab"); c1.add("ca"); Collection<String> c2 = c1.stream().filter(s -> s.startsWith("a")).collect(Collectors.toCollection(ArrayList::new)); Collection<String> c3 = c1.stream().filter(s -> s.startsWith("a")).collect(Collectors.toList()); c2.forEach(System.out::println); // prints-> aa ab c3.forEach(System.out::println); // prints-> aa ab