当前位置: 首页 > 知识库问答 >
问题:

使用java 8映射、过滤和收集时,是创建新对象还是修改现有对象?

贡英华
2023-03-14

我有下面的代码,我正在使用映射内的过滤器和替换函数进行过滤,然后我正在进行收集以替换原始数组。我的问题是,输入Arr中的原始对象是否被丢弃并创建新对象,还是在我进行收集时修改相同的对象?

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个答案

贺景胜
2023-03-14

任何修改字符串的方法都必须返回一个新对象,因为字符串根据定义是不可变的。因此,

forEach(u -> u.replaceAll("2","X"))

为流中的每个元素创建一个新字符串,然后立即丢弃它,因为返回值被忽略。

至于第二个流中的 filterReplace() 方法,它根本不是修改,它只是返回输入字符串或其他预定义值 (“X”)。重新分配该变量后,inputArr 中的原始对象可能会被丢弃,但在流中没有创建新对象。

伊铭
2023-03-14

好的,如果我理解正确的话,您想知道< code>collect或< code>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;
    }
}

还有一个小用法,firs with 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]

请注意,它是相同的哈希-列表中的对象没有更改。参考文献相同。您所更改的是对象的内部。

对于<code>collect<code>也会发生同样的情况:

    System.out.println(list);
    List<MyObject> result = list.stream().filter(x -> x.getValue() > 0).collect(Collectors.toList());
    System.out.println(result);

这里有两件主要的事情。流在现有源上迭代,如果在流中更改某些属性(如<code>forEach</code>示例),则已更改源。

您不应该更改您的流的源,因为这是文档所禁止的。这或者叫做不干涉,或者叫做副作用。

 类似资料:
  • 给定的类值: 我正在尝试使用创建该类的一个新实例: 如果是,我如何使用创建一个新的值对象,在这里我调用的? 谢谢

  • 假设我有一个Foo对象列表。Foo上有一个属性,我必须使用它从数据源中获取Bar对象。然后我必须将每个bar对象映射回我得到bar的原始Foo对象。 我的尝试如下:

  • 我正在学习使用Java8和Stream做事情。我有一个问题,我正试图用java8流解决这个问题。 我有一个地图类型

  • 问题内容: 给定班级价值: 我正在尝试使用创建该类的新实例: 从主要: 这不起作用,Eclipse的输出: 如果是这样,怎么可以用我创建了一个新的价值目标,在那里我调用的? 谢谢 问题答案: 您需要为此找到确切的构造函数。只能用于调用null构造函数。所以写

  • 问题内容: 我正在尝试设计一个非常简单的应用程序,并使自己与Hibernate的实体和值对象的定义(在Java Persistence with Hibernate的第4章中定义)有些困惑。 我所拥有的是带有客户的应用程序,可以下订单(一对多关系)。这些订单中的每一个都有许多订单行(也是一对多)。现在,我认为客户具有身份(客户编号),订单(订单编号)也是如此,因此它们是实体对象吗?我的困惑来自订单