我有下面的代码,我正在使用过滤器进行过滤并替换我的地图中的函数,然后我正在进行收集以替换我的原始数组。我的问题是我在inputArr中的原始对象是否被丢弃并且是否创建了新对象,或者在进行收集时是否修改了相同的对象?
public static void test () {
inputArr.stream().filter(s -> toRemove.contains(s)).
forEach(u -> u.replaceAll("2","X"));
inputArr = inputArr.stream().map(x -> filterReplace(x,toRemove)).collect(Collectors.toList());
System.out.println(inputArr);
}
static String filterReplace(String input, Set<String> toRemove) {
if (toRemove.contains(input)) {
return "X";
}
else
return input;
}
答案 0 :(得分:1)
好的,如果我理解正确,您想知道collect
或forEach
是否修改了原始来源。你可以自己轻松测试一下。我们有一个小班供测试:
static class MyObject {
private int value;
public MyObject(int value) {
super();
this.value = value;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
@Override
public String toString() {
return System.identityHashCode(this) + " " + value;
}
}
一小部分用法,第一次使用forEach
:
MyObject first = new MyObject(1);
MyObject second = new MyObject(2);
List<MyObject> list = Arrays.asList(first, second);
System.out.println(list);
list.stream().forEach(x -> x.setValue(x.getValue() + 1));
System.out.println(list);
如果你打印这些:
[1018081122 1, 242131142 2]
[1018081122 2, 242131142 3]
请注意,它的相同的哈希 - 对象在列表中没有更改。参考文献是相同的。您更改的是Object的 internals 。
collect
会发生同样的事情:
System.out.println(list);
List<MyObject> result = list.stream().filter(x -> x.getValue() > 0).collect(Collectors.toList());
System.out.println(result);
这里有两件主要的事情要做。 Streams 遍历现有源,如果您在流中更改了某些属性(例如在forEach
示例中),则更改了源。
您不应更改来源,因为文档禁止这样做。这称为非干扰或副作用。
答案 1 :(得分:0)
修改字符串的任何方法都必须返回一个新对象,因为字符串根据定义是不可变的。因此,
forEach(u -> u.replaceAll("2","X"))
为流中的每个元素创建一个新字符串,然后立即丢弃它,因为忽略了返回值。
对于第二个流中的filterReplace()
方法,它根本没有修改,它只返回输入字符串或另一个预定义值("X"
)。重新分配变量后,inputArr
中的原始对象可能会被丢弃,但流中没有创建新对象。