在包含Streams的2D列表的修改列表中包含未修改列表中的元素
我问这个问题是关于对1D列表做同样的事情,认为将答案应用于2D列表会很容易,但事实并非如此。
基于Holger的答案我的代码,我提出了这个解决方案:
//list is of type ArrayList<List> 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 map(Function)
,但是,当我尝试这个时。
如何在2D列表上执行此function?
一些示例输入和输出:
[[1, 2, 3, 4], [5, 6, 7, 8]]
应输出[[-1, 0, 1, 4], [3, 4, 5, 8]]
你的括号有问题。 改变这个:
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());
缩进在这里很重要,可以提高代码的可读性。 我会重新推出第二个片段如下:
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 modifyAllButLast(List 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
方法引用。
让我们一步一步修复错误
Stream#concat将两个流连接在一起,但是你连接一个是List
而不是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()) // it returns List ---^ )).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
但它返回>
List
。 我们可以将连接的流收集到List
,如下所示:
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 to List ).collect(Collectors.toList());
但我认为在这种情况下最好的方法是使用List#replaceAll ,我已经在你的另一个问题中回答了这个问题 ,因为Stream
比Collector
更重,所以更具表现力和更快 。
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());
这可能不是连接两个列表的最优雅方式,但它会做到这一点。
list.stream() .map(integerList -> { List 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());