繁体   English   中英

Java8:关于Collectors.groupingBy返回的Map元素的顺序

[英]Java8: About order of Map elements returned by Collectors.groupingBy

希望就从示例中修改的以下代码寻求建议。

我想知道更改输入List元素序列时,结果Map中的输出序列是否会改变。 但是,似乎输出在所有情况下都是相同的(我在IDE上反复运行了该程序)。 我是否可以就是否可以预期生成的Map元素的顺序寻求建议? 使用枚举或字符串时,顺序(字母/非字母顺序)会有所区别吗,还是元素顺序只是随机的?

public class TestCountry {

    public enum Continent {ASIA, EUROPE}

    String name;
    Continent region;

    public TestCountry (String na, Continent reg) {
        name = na;
        region = reg;
    }

    public String getName () {
        return name;
    }

    public Continent getRegion () {
        return region;
    }

    public static void main(String[] args) {
        List<TestCountry> couList1 = Arrays.asList (
                new TestCountry ("Japan", TestCountry.Continent.ASIA),
                new TestCountry ("Italy", TestCountry.Continent.EUROPE),
                new TestCountry ("Germany", TestCountry.Continent.EUROPE));

        List<TestCountry> couList2 = Arrays.asList (
                new TestCountry ("Italy", TestCountry.Continent.EUROPE),
                new TestCountry ("Japan", TestCountry.Continent.ASIA),
                new TestCountry ("Germany", TestCountry.Continent.EUROPE));

        Map<TestCountry.Continent, List<String>> mapWithRegionAsKey1 = couList1.stream ()
                    .collect(Collectors.groupingBy (TestCountry ::getRegion,
                        Collectors.mapping(TestCountry::getName, Collectors.toList())));

        Map<String, List<Continent>> mapWithNameAsKey1 = couList1.stream ()
                    .collect(Collectors.groupingBy (TestCountry::getName,
                        Collectors.mapping(TestCountry::getRegion, Collectors.toList())));

        Map<TestCountry.Continent, List<String>> mapWithRegionAsKey2 = couList2.stream ()
                    .collect(Collectors.groupingBy (TestCountry ::getRegion,
                        Collectors.mapping(TestCountry::getName, Collectors.toList())));

        Map<String, List<Continent>> mapWithNameAsKey2 = couList2.stream ()
                    .collect(Collectors.groupingBy (TestCountry::getName,
                        Collectors.mapping(TestCountry::getRegion, Collectors.toList())));

        System.out.println("Value of mapWithRegionAsKey1 in couList1: " + mapWithRegionAsKey1);
        System.out.println("Value of mapWithNameAsKey1 in couList1: " + mapWithNameAsKey1);

        System.out.println("Value of mapWithRegionAsKey2 in couList2: " + mapWithRegionAsKey2);
        System.out.println("Value of mapWithNameAsKey2 in couList2: " + mapWithNameAsKey2);
    }
}

/*
 * Output:
Value of mapWithRegionAsKey1 in couList1: {ASIA=[Japan], EUROPE=[Italy, 
Germany]}
Value of mapWithNameAsKey1 in couList1: {Japan=[ASIA], Italy=[EUROPE], 
Germany=[EUROPE]}
Value of mapWithRegionAsKey2 in couList2: {ASIA=[Japan], EUROPE=[Italy, 
Germany]}
Value of mapWithNameAsKey2 in couList2: {Japan=[ASIA], Italy=[EUROPE], 
Germany=[EUROPE]}
 */

Collectors.groupingBy()当前返回一个HashMap 这是一个实现细节,可以在将来的版本中更改。

HashMap的条目未排序,但是它们的迭代顺序(在打印HashMap )是确定性的,并且不取决于插入顺序。

因此,无论输入List元素的顺序如何,您都会看到相同的输出。 但是,您不应该依赖该顺序,因为它是实现细节。

如果您关心输出Map条目的顺序,则可以修改代码以生成LinkedHashMap (默认顺序为插入顺序)或TreeMap (对键进行排序)。

顺便说一句,如果您将输入更改为

    List<TestCountry> couList1 = Arrays.asList (
            new TestCountry ("Japan", TestCountry.Continent.ASIA),
            new TestCountry ("Italy", TestCountry.Continent.EUROPE),
            new TestCountry ("Germany", TestCountry.Continent.EUROPE));

    List<TestCountry> couList2 = Arrays.asList (
            new TestCountry ("Germany", TestCountry.Continent.EUROPE),
            new TestCountry ("Italy", TestCountry.Continent.EUROPE),
            new TestCountry ("Japan", TestCountry.Continent.ASIA)
            );

您将在输出中得到不同的顺序:

couList1中mapWithRegionAsKey1的值:{ASIA = [Japan],EUROPE = [ Italy,Germany ]}
couList1中mapWithNameAsKey1的值:{Japan = [ASIA],意大利= [EUROPE],德国= [EUROPE]}
couList2中mapWithRegionAsKey2的值:{ASIA = [Japan],EUROPE = [ Germany,Italy ]}
couList2中mapWithNameAsKey2的值:{Japan = [ASIA],意大利= [EUROPE],德国= [EUROPE]}

这是由于各个输出List的元素(在当前实现中为ArrayList )是根据插入顺序进行排序的,这取决于输入List的顺序。

在质疑之前,请阅读说明以下内容的文档:

不保证返回的Map或List对象的类型 ,可变性,可序列化性或线程安全性。

因此,如果您无法确定返回的地图类型,就无法真正确定将返回的顺序(如果有)。 好吧, 正如Eran指出的那样,它是一个HashMap ,但这不能保证。

问题是您为什么要介意呢? 如果是出于学术目的,那么就有意义,如果不是,那就收集一些可以保证订单的东西。

Collectors.groupingBy采用一个参数,可让您指定您可能需要的实际Map实现。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM