Java 8流是否可以收集两个列表?

8

假设我有一个包含两种数据类型的列表,一种是有效的,另一种是无效的。

如果我开始过滤这个列表,最终能否收集到两个列表?


1
欢迎来到StackOverflow。请在这里阅读如何提问的详细说明:https://stackoverflow.com/help/how-to-ask请详细解释你的问题。你已经尝试了什么?你所说的“无效”是什么意思? - Jayendran
5个回答

9
我们不能直接从Java 8的流中收集两个列表,但是如果您有一种方法可以根据条件对列表元素进行分组,那么您可以使用Collectors.groupingBy()。在这种情况下,它将返回一个Map<Foo,List<Bar>>, 其中Map的值是这两个列表。请注意,在您的情况下,您不需要流仅执行过滤操作。使用removeIf()筛选无效列表,并将其所有元素添加到第一个列表中:
invalidList.removeIf(o -> conditionToRemove);
goodList.addAll(invalidList);      

如果您不想改变goodList的状态,可以进行浅复制:

invalidList.removeIf(o -> conditionToRemove);
List<Foo> terminalList = new ArrayList<>(goodList);
terminalList.addAll(invalidList);

感谢您提供的解决方案。 - user10179187

4

这是一种使用Java 8流API的方法。假设我有一个List字符串元素:输入列表具有不同长度的字符串;只有长度为3的字符串有效。

List<String> input = Arrays.asList("one", "two", "three", "four", "five");
Map<Boolean, List<String>> map = input.collect(Collectors.partitioningBy(s -> s.length() == 3));
System.out.println(map); // {false=[three, four, five], true=[one, two]}

生成的Map只有两条记录:一个是有效输入列表元素的键值对,另一个是无效输入列表元素的键值对。键为true的记录包含有效字符串作为List:one, two。另一个键为false的记录包含无效字符串:three, four, five。

请注意,Collectors.partitioningBy始终在生成的Map中产生两条记录,不管存在有效或无效的值。


1
第二行代码必须使用流方法进行编译: Map<Boolean, List<String>> map = input.stream().collect(Collectors.partitioningBy(s -> s.length() == 3)); - Martin P.
@MartinP。你是正确的 - 我没有注意到它。谢谢你指出来。也许我在想类似于input = Stream.of("one", "two", "three", "four", "five")这样的东西,然后打错了://3 - prasad_

2

收集器只能返回一个对象!

但是您可以创建一个自定义收集器,将流元素简单地放入两个列表中,然后返回包含这两个列表的列表。

有很多例子来说明如何做到这一点。


感谢提供创建自定义收集器的链接。 - user10179187

2
另一个建议:使用一个 lambda 过滤器,将你想从流中过滤掉的元素添加到一个单独的列表中。

感谢您提供的解决方案。我也实施了相同的解决方案。 - user10179187
如果你想使用并行流,这种方法效果不佳。 - jbaranski

1

如果您需要对二进制(true|false)进行分类,可以使用Collectors.partitioningBy,它将返回Map<Boolean, List>(或其他下游集合,如Set,如果您另外指定)。

如果您需要超过2个类别,请使用groupBy或仅使用集合的Collectors.toMap


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接