2016-05-16 38 views
4

考虑一个列表List<People>,其中元素按照People.getAge()的升序排序。如果我们使用Collectors.groupingBy(People::getCity)将此列表分组,那么每个组/城市的结果列表是否仍按年龄排序?Java分组收藏者保存列表顺序吗?

实际上,它似乎确实保存了顺序。我在寻找保证。

对于该方法的Javadoc说:

如果不需要的顺序保存在其中元素出现在所得到的地图集电极,使用groupingByConcurrent(功能)可以提供更好的并行性能

我不确定这是否涉及列表中的项目顺序。

+1

你的Javadoc报价显然很明显。你为什么怀疑? –

+0

@FrankPuffer:通过地图收集器,它是否指用于构建地图元素的toList收集器? – Prateek

+0

@FrankPuffer:确实上面的报价*表明* groupingBy保留了订单,但遗憾的是['Collectors.groupingBy''s JavaDoc](http://docs.oracle.com/javase/8/docs/api /java/util/stream/Collectors.html#groupingBy-java.util.function.Function-)并没有对此做任何说明。这很糟糕,因为虽然我们可以看OpenJDK的实现或做实证测试,但他们告诉我们的只是实现目前的功能,而不是合同的内容。所以希望它能在JDK API文档中的某处进行说明。 –

回答

1

理解合同的关键在于它说“元素出现的顺序为”。它谈到他们是否按顺序到达,这意味着他们是否被传递到关键提取器Function和顺序的任何下游收集器;它并没有说任何关于这个订单是否会保留在任何产生的积累中;实际上groupingBy的当前实现使用不保存密钥顺序的HashMap

您询问它是否涉及列表中项目的顺序。如果您引用的是创建流的列表,则在列表上创建的流的确开始排序,但某些流操作会更改顺序或使其无序,因此它引用的顺序指的是管道后的结果顺序如果流保持有序,则操作完成。如果流操作使流无序,则元素在收集器上出现的顺序不再是问题。

如果您指的是List中项目的顺序,那么收集分组的项目,是的,因为“元素出现的顺序”是元素处理的顺序。分组到下游收集器时也是如此;如果流仍然是有序的,并且您将组合到保留顺序的下游收集器,则这将保留该顺序,而并行版本可能不会。

+0

引用的Javadoc是“如果保存元素出现在**生成的** Map ...中的顺序”。确切地说,它只是说** **结果**中的顺序被保留下来,为此它可以被解释为:给定相同的输入,不管你处理了多少次,结果顺序是相同的。为此,只要结果一致,即使是**传入**流中的排序也不会被保留,它仍然能够满足Javadoc所说的内容。 (我也相信Javadoc的初衷是说对应于输入保存排序,但它被写成w/ambiguities) –