最近,我了解了Java 8中的流,并开始使用它们。现在我有一个关于groupingBy收集器方法的问题:
通常我使用的是.NET,所以我比较了(知道它们是而不是) Java Stream<T>和.NET IEnumerable<T>。在进行此比较之后,List<T>存储元素,而特定的Stream/IEnumerable应用操作。一个例子是:
C#:
elements.Where(x => x.Value == 5).ToList();爪哇:
elements.stream().filter(x -> x.getValue() == 5).collect(Collectors.toList());在这两个示例中,我从一个列表开始,定义操作(本例中是一个过滤器)并收集结果来存储它(本例中的一个新列表)。
现在我有了一个更复杂的案子:
data.stream()
.map( ... ).filter( ... ) // Some operations
.collect(groupingBy(Chunk::getName, summingLong(Chunk::getValue)));这个查询的结果是一个Map<String, Long>,我可以使用它,但是让我说,我想继续处理这个数据,而不是存储它。我目前的方法是微不足道的:
...
.collect(groupingBy(Chunk::getName, summingLong(Chunk::getValue)))
.entrySet().stream().
.map( ... ) // Do more operations但是这样,我就离开了流,将第一个结果存储在Map中,然后打开一个新的流继续。有没有办法在没有收集器的情况下进行分组,这样我就可以“呆在”流中了?
发布于 2017-01-09 13:33:02
因为API是现在的,你不能逃避它。
groupingBy
是终端操作(它不返回流),因此操作将结束流。
根据您以后在上一次映射操作中想要做的事情,您可以创建一个自定义收集器,该收集器将“留在”流中;即使在流中,您可能仍然会将元素收集到Map中。
发布于 2017-01-09 13:46:32
您可以在下游收集器中任意操作,只要您可以将操作描述为Collector。目前,只有一个与中间操作map ( mapping收集器)等价的操作,但是JavaCanced9也会添加filtering和flatMapping (您也可以在Java 8中实现这些操作),而且几乎每个终端操作都有一个等价的。
当然,嵌套的收集器设备看起来将与执行相同…的流操作链完全不同
但是,如果您想要处理完整的组,则无法首先完成grouping集合。这不是API的限制,而是分组操作或任何操作的内在特性,如果您想要处理一个完整的结果,则需要首先完成该操作。不管API是什么样子的,例如,您可以以collectingAndThen-like的方式在收集器中隐藏后续操作,创建和填充Map是不可避免的,因为这是执行组维护的映射。组由Map的键和查找逻辑确定,因此,例如,使用带有自定义比较器或IdentityHashMap的SortedMap可以完全改变分组逻辑。
https://stackoverflow.com/questions/41549005
复制相似问题