我想知道是否可以使用流来调用列表中每个元素的函数,以及 修改 它的值。
假设我有一个整数列表:List<Integer> list = Arrays.asList(1,2,3);
一种将每个数字递增一个的方法:
public static Integer plusOne(Integer n){
return n + 1;
}
这是我以前在每个元素上调用函数并修改原始列表的原因:
for (int i = 0; i < list.size(); i++){
list.set(i, plusOne(list.get(i)));
}
但是,我想知道是否有更短的方式使用流写这个?
我尝试使用:
list.stream()
.forEach(e -> plusOne(e));
但它似乎没有更改原始列表,也没有返回任何内容......如果使用流更改原始列表是不可能的,我怎么能至少获得列表的新修改副本?
顺便说一句,在调用列表中的函数之后,输出应该是(2,3,4)的列表。
答案 0 :(得分:3)
不需要Stream。您可以使用List.replaceAll:
list.replaceAll(MyApplication::plusOne);
答案 1 :(得分:2)
您需要将map
与collect
一起使用,因为stream
不会修改现有列表,例如:
public static int plusOne(int i){
return i + 1;
}
public static void main(String[] args) throws Exception{
List<Integer> list = Arrays.asList(1,2,3);
List<Integer> updated = list.stream()
.map(i -> plusOne(i))
.collect(Collectors.toList());
System.out.println(updated);
}
甚至,
List<Integer> updated = list.stream()
.map(i -> i + 1)
.collect(Collectors.toList());
System.out.println(updated);
答案 2 :(得分:1)
您可以通过以下习语对您的List
进行变异播放。
请注意,这是绝对可怕的代码,并且完全构成了可怕的做法。
仅用于试验。
List<Integer> list = Arrays.asList(1,2,3);
// cannot have a re-assignable index here as it requires being effectively final
int[] i = {0};
// iterating list
list.forEach(
// for each element...
(e) ->
// setting list at current index and incrementing index, with current value + 1
list.set(i[0]++, e + 1)
);
System.out.println(list);
<强>输出强>
[2, 3, 4]
备注强>
List
,将值映射到其增量并收集为List
(请参阅Darshan的答案的第二部分一个简单的例子)答案 3 :(得分:1)
虽然有很多方法可以随时修改输入列表,但我们已经学会避免这样做,因为它会导致问题。
您可以非常轻松地将现有列表(在当前范围内)替换为新列表:
list = list.stream().map(...).collect(Collectors.toList());
这很干净。您的旧列表仍然存在(直到潜在的垃圾收集)。对它的任何其他引用都看不到任何变化 - 这是健康的。如果没有更多的引用,它就会被垃圾收集。