展平一个集合

新手上路,请多包涵

假设我有一个 Map<? extends Object, List<String>>

我可以很容易地获取地图的值,并对其进行迭代以生成单个 List<String>

    for (List<String> list : someMap.values()) {
        someList.addAll(list);
    }

有没有办法一次把它弄平?

   List<String> someList = SomeMap.values().flatten();

原文由 Tony Ennis 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 352
2 个回答

如果你使用的是 Java 8,你可以这样做:

 someMap.values().forEach(someList::addAll);

原文由 Josh M 发布,翻译遵循 CC BY-SA 3.0 许可协议

使用 Java 8,如果您不想自己实例化一个 List 实例,就像在建议(和接受)的解决方案中一样

someMap.values().forEach(someList::addAll);

您可以通过使用以下语句进行流式传输来完成所有操作:

 List<String> someList = map.values().stream().flatMap(c -> c.stream()).collect(Collectors.toList());

顺便说一句,有趣的是,在 Java 8 上,公认的版本似乎确实是最快的。它的时间与

for (List<String> item : someMap.values()) ...

并且比纯流媒体解决方案更快。这是我的小测试代码。我明确地不将其命名为基准以避免由此引起的对基准缺陷的讨论。 ;) 我每次测试都做了两次,希望能得到一个完整的编译版本。

     Map<String, List<String>> map = new HashMap<>();
    long millis;

    map.put("test", Arrays.asList("1", "2", "3", "4"));
    map.put("test2", Arrays.asList("10", "20", "30", "40"));
    map.put("test3", Arrays.asList("100", "200", "300", "400"));

    int maxcounter = 1000000;

    System.out.println("1 stream flatmap");
    millis = System.currentTimeMillis();
    for (int i = 0; i < maxcounter; i++) {
        List<String> someList = map.values().stream().flatMap(c -> c.stream()).collect(Collectors.toList());
    }
    System.out.println(System.currentTimeMillis() - millis);

    System.out.println("1 parallel stream flatmap");
    millis = System.currentTimeMillis();
    for (int i = 0; i < maxcounter; i++) {
        List<String> someList = map.values().parallelStream().flatMap(c -> c.stream()).collect(Collectors.toList());
    }
    System.out.println(System.currentTimeMillis() - millis);

    System.out.println("1 foreach");
    millis = System.currentTimeMillis();
    for (int i = 0; i < maxcounter; i++) {
        List<String> mylist = new ArrayList<String>();
        map.values().forEach(mylist::addAll);
    }
    System.out.println(System.currentTimeMillis() - millis);

    System.out.println("1 for");
    millis = System.currentTimeMillis();
    for (int i = 0; i < maxcounter; i++) {
        List<String> mylist = new ArrayList<String>();
        for (List<String> item : map.values()) {
            mylist.addAll(item);
        }
    }
    System.out.println(System.currentTimeMillis() - millis);


    System.out.println("2 stream flatmap");
    millis = System.currentTimeMillis();
    for (int i = 0; i < maxcounter; i++) {
        List<String> someList = map.values().stream().flatMap(c -> c.stream()).collect(Collectors.toList());
    }
    System.out.println(System.currentTimeMillis() - millis);

    System.out.println("2 parallel stream flatmap");
    millis = System.currentTimeMillis();
    for (int i = 0; i < maxcounter; i++) {
        List<String> someList = map.values().parallelStream().flatMap(c -> c.stream()).collect(Collectors.toList());
    }
    System.out.println(System.currentTimeMillis() - millis);

    System.out.println("2 foreach");
    millis = System.currentTimeMillis();
    for (int i = 0; i < maxcounter; i++) {
        List<String> mylist = new ArrayList<String>();
        map.values().forEach(mylist::addAll);
    }
    System.out.println(System.currentTimeMillis() - millis);

    System.out.println("2 for");
    millis = System.currentTimeMillis();
    for (int i = 0; i < maxcounter; i++) {
        List<String> mylist = new ArrayList<String>();
        for (List<String> item : map.values()) {
            mylist.addAll(item);
        }
    }
    System.out.println(System.currentTimeMillis() - millis);

结果如下:

 1 stream flatmap
468
1 parallel stream flatmap
1529
1 foreach
140
1 for
172
2 stream flatmap
296
2 parallel stream flatmap
1482
2 foreach
156
2 for
141

编辑 2016-05-24(两年后):

在同一台机器上使用实际的 Java 8 版本 (U92) 运行相同的测试:

 1 stream flatmap
313
1 parallel stream flatmap
3257
1 foreach
109
1 for
141
2 stream flatmap
219
2 parallel stream flatmap
3830
2 foreach
125
2 for
140

似乎流的顺序处理速度加快,并行流的开销更大。

编辑 2018-10-18(四年后):

现在在同一台机器上使用 Java 10 版本 (10.0.2):

 1 stream flatmap
393
1 parallel stream flatmap
3683
1 foreach
157
1 for
175
2 stream flatmap
243
2 parallel stream flatmap
5945
2 foreach
128
2 for
187

并行流的开销似乎更大。

编辑 2020-05-22(六年后):

现在在另一台机器上使用 Java 14 版本 (14.0.0.36):

 1 stream flatmap
299
1 parallel stream flatmap
3209
1 foreach
202
1 for
170
2 stream flatmap
178
2 parallel stream flatmap
3270
2 foreach
138
2 for
167

真的应该指出,这是在不同的机器上完成的(但我认为具有可比性)。并行流开销似乎比以前小得多。

编辑 2022-09-25(八年后):

现在在一台可能不同的机器上使用 Java 17 版本(17.0.4.101-hotspot)(我不记得最后一个 :():

 1 stream flatmap
473
1 parallel stream flatmap
3109
1 foreach
193
1 for
233
2 stream flatmap
257
2 parallel stream flatmap
2453
2 foreach
200
2 for
211

并行开销再次变小。再次记住另一台机器。

原文由 wumpz 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏