使用java 8 map,filter和collect时,是创建新对象还是修改现有对象?

时间:2017-06-04 07:13:04

标签: java functional-programming java-stream

我有下面的代码,我正在使用过滤器进行过滤并替换我的地图中的函数,然后我正在进行收集以替换我的原始数组。我的问题是我在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;
}

2 个答案:

答案 0 :(得分:1)

好的,如果我理解正确,您想知道collectforEach是否修改了原始来源。你可以自己轻松测试一下。我们有一个小班供测试:

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中的原始对象可能会被丢弃,但流中没有创建新对象。