【问题标题】:Including elements from unmodified lists in modified lists in a 2D list with Streams将未修改列表中的元素包含在带有 Streams 的 2D 列表中的已修改列表中
【发布时间】:2017-05-29 16:51:01
【问题描述】:

我向this 询问了关于对一维列表做同样事情的问题,我认为将答案应用于二维列表很容易,但事实并非如此。

基于我的代码 Holger's 答案,我想出了这个解决方案:

//list is of type ArrayList<List<Integer>>
list.stream()
        .map(l -> Stream.concat(
                l.subList(0, l.size() - 1).stream().map(i -> i - 2),
                Stream.of(l.get(l.size() - 1)).collect(Collectors.toList())
        ))
        .collect(Collectors.toList());

但是,当我尝试这个时,我得到了编译时错误Cannot infer type argument(s) for &lt;R&gt; map(Function&lt;? super T,? extends R&gt;)

如何在二维列表上执行此功能?

一些示例输入和输出:

[[1, 2, 3, 4], [5, 6, 7, 8]] 应该输出[[-1, 0, 1, 4], [3, 4, 5, 8]]

【问题讨论】:

    标签: java list java-8 java-stream


    【解决方案1】:

    括号有问题。改变这个:

    list.stream()
        .map(l -> Stream.concat(
                l.subList(0, l.size() - 1).stream().map(i -> i - 2),
                Stream.of(l.get(l.size() - 1)).collect(Collectors.toList())
        ))
        .collect(Collectors.toList());
    

    到这里:

    list.stream()
        .map(l -> Stream.concat(
                l.subList(0, l.size() - 1).stream().map(i -> i - 2),
                Stream.of(l.get(l.size() - 1))).collect(Collectors.toList())
        )
        .collect(Collectors.toList());
    

    缩进在这里很重要,可以提高代码的可读性。我将按如下方式重新缩进第二个 sn-p:

    list.stream()
        .map(l -> Stream.concat(
                l.subList(0, l.size() - 1).stream().map(i -> i - 2),
                Stream.of(l.get(l.size() - 1)))
            .collect(Collectors.toList()))
        .collect(Collectors.toList());
    

    或者更好的是,我会将修改内部列表的逻辑移至辅助方法:

    public final class Utility {
        private Utility() { }
    
        public static List<Integer> modifyAllButLast(List<Integer> list) {
            return Stream.concat(
                    l.subList(0, l.size() - 1).stream().map(i -> i - 2),
                    Stream.of(l.get(l.size() - 1)))
                .collect(Collectors.toList());
        }
    }
    

    然后我会从外部流中使用这个方法:

    list.stream()
        .map(Utility::modifyAllButLast)
        .collect(Collectors.toList());
    

    注意:无需将辅助方法移至新的Utility 类,您甚至可以让它成为非静态方法。在这种情况下,只需相应地更改 Utility::modifyAllButLast 方法引用即可。

    【讨论】:

      【解决方案2】:

      让我们一步一步修复错误

      Stream#concat 将两个流连接在一起,但你连接的一个是 List&lt;Integer&gt; 而不是 Stream&lt;Integer&gt;

      list.stream().map(l -> Stream.concat(
          l.subList(0, l.size() - 1).stream().map(i -> i - 2),
          Stream.of(l.get(l.size() - 1)).collect(Collectors.toList())
         // it returns List<Integer> ---^
      )).collect(Collectors.toList());
      

      那么我们可以通过返回Stream 来修复错误,如下所示:

      list.stream().map(l -> Stream.concat(
          l.subList(0, l.size() - 1).stream().map(i -> i - 2),
          Stream.of(l.get(l.size() - 1))
      )).collect(Collectors.toList());
      

      结果与预期不符。我们预计它会返回一个List&lt;List&lt;Integer&gt;&gt;,但它会返回一个List&lt;Stream&lt;Integer&gt;&gt;。我们可以将连接的流收集到List&lt;Integer&gt;,如下所示:

      list.stream().map(main -> 
          Stream.concat(
              main.subList(0, main.size() - 1).stream().map(i -> i - 2),
              Stream.of(main.get(main.size() - 1))           
          ).collect(Collectors.toList())
      //   ^--- collecting Stream<Integer> to List<Integer>
      ).collect(Collectors.toList());
      

      但是我认为在这种情况下最好的方法是使用我在您的another question 中回答的List#replaceAll,这更表现力更快 因为StreamCollector 重。

      list.stream().map(main ->
          main.stream().collect(collectingAndThen(toList(), it -> {
              // v--- replacing all items in list except the last one 
              it.subList(0, it.size() - 1).replaceAll(item -> item - 2);
              return it;
          }))
      ).collect(Collectors.toList());
      

      【讨论】:

        【解决方案3】:

        这可能不是连接两个列表的最优雅的方式,但它会做到。

        list.stream()
            .map(integerList -> {
                List<Integer> toReturn = integerList
                        .subList(0, integerList.size() - 1)
                        .stream()
                        .map(i -> i - 2)
                        .collect(Collectors.toList());
                toReturn.add(integerList.get(integerList.size() - 1));
                return toReturn;
            })
            .collect(Collectors.toList());
        

        【讨论】:

          猜你喜欢
          • 2020-11-02
          • 2012-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-20
          • 2011-09-17
          • 1970-01-01
          相关资源
          最近更新 更多