【问题标题】:Creating Map composed of 2 Lists using stream().collect in Java在 Java 中使用 stream().collect 创建由 2 个列表组成的地图
【发布时间】:2016-10-10 16:33:28
【问题描述】:

例如,有两个列表:

List<Double> list1 = Arrays.asList(1.0, 2.0);
List<String> list2 = Arrays.asList("one_point_zero", "two_point_zero");

使用 Stream,我想创建一个由这些列表组成的映射,其中 list1 用于键,list2 用于值。为此,我需要创建一个辅助列表:

List<Integer> list0 = Arrays.asList(0, 1);

这是地图:

Map<Double, String> map2 = list0.stream()
                .collect(Collectors.toMap(list1::get, list2::get));

list0 按 list1::get 和 list2::get 的顺序使用。有没有更简单的方法而不创建list0?我尝试了以下代码,但没有成功:

Map<Double, String> map2 = IntStream
                .iterate(0, e -> e + 1)
                .limit(list1.size())
                .collect(Collectors.toMap(list1::get, list2::get));

【问题讨论】:

  • 答案找到了:我应该用 Stream.iterate(0, e -> e + 1) 而不是 IntStream.iterate(0, e -> e + 1)
  • 这样您就可以关闭问题
  • 不,不要使用Stream.iterate(0, e -&gt; e + 1).limit(list1.size())。使用IntStream.range(0, list1.size()).boxed()。与直接的range 流相比,iteratelimit 的组合具有明显的性能缺陷。将IntStream 转换为Stream&lt;Integer&gt; 就像链接boxed() 一样简单。你甚至可以完全避免盒装Integers:IntStream.range(0, list1.size()).collect(HashMap::new, (m,i) -&gt; m.put(list1.get(i),list2.get(i)), Map::putAll)

标签: java java-8 java-stream collectors


【解决方案1】:

您可以让它们由IntStream 生成,而不是使用辅助列表来保存索引。

Map<Double, String> map = IntStream.range(0, list1.size())
            .boxed()
            .collect(Collectors.toMap(i -> list1.get(i), i -> list2.get(i)));

【讨论】:

    【解决方案2】:

    确实,最好的方法是使用IntStream.range(startInclusive, endExclusive) 以便使用get(index) 访问两个列表的每个元素,最后使用Math.min(a, b) 以避免在列表大小不完全相同的情况下获得IndexOutOfBoundsException,所以最终的代码是:

    Map<Double, String> map2 = IntStream.range(0, Math.min(list1.size(), list2.size()))
        .boxed()
        .collect(Collectors.toMap(list1::get, list2::get));
    

    【讨论】:

    • 虽然这个答案与@svarog 的答案基本相同,但我喜欢使用Math.min::get 方法引用(而不是lambda),它们看起来更干净、更安全。
    【解决方案3】:

    这对我有用,但 O(n^2):

        Map<Double, String> collect =
                list1.stream()
                        .collect(
                                toMap(Double::doubleValue, 
                                        item -> list2.get(list1.indexOf(item))));
    

    【讨论】:

    • 这看起来可行,但indexOf 可能非常昂贵,特别是对于长列表和具有复杂值的列表(例如String)。评分最高的两个答案更好。
    猜你喜欢
    • 2018-10-16
    • 1970-01-01
    • 2017-03-27
    • 2020-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-17
    • 1970-01-01
    相关资源
    最近更新 更多