Java流映射修改未内置在类中的自定义类对象

时间:2018-09-27 06:57:14

标签: java java-8 java-stream

class Employee {

    public String name;
    public Integer age;
    public Employee(String n, int age) {
        this.name = n;
        this.age = age;
    }
    public String toString() {
        return this.name+":"+this.age;
    }
}

在Main内部:

ArrayList<Employee> list = new ArrayList<>();
list.add(new Employee("NameA", 10));
list.add(new Employee("NameB", 25));
list.add(new Employee("NameC", 30));
list.add(new Employee("NameD", 45));
list.add(new Employee("NameE", 50));

System.out.println(list);//[NameA:10, NameB:25, NameC:30, NameD:45, NameE:50]

list.stream().filter(e->e.age%10==0).map(e->e.name+="CHANGE").collect(Collectors.toList());

System.out.println(list); //[NameACHANGE:10, NameB:25, NameCCHANGE:30, NameD:45, NameECHANGE:50]


ArrayList<String> strList = new ArrayList<>();
strList.add("1");
strList.add("2");
strList.add("3");
strList.add("4");
strList.add("5");

System.out.println(strList);//[1, 2, 3, 4, 5]

List<String> updatedStrList = strList.stream().map(s->s+="CHANGE").collect(Collectors.toList());

System.out.println(updatedStrList);//[1CHANGE, 2CHANGE, 3CHANGE, 4CHANGE, 5CHANGE]

System.out.println(strList);//[1, 2, 3, 4, 5]

这种行为的原因是什么? 更改Employee对象的值时,该值将在原始ArrayList中更新,但是当更改String的ArrayList时,该值不会反映在原始ArrayList中。

2 个答案:

答案 0 :(得分:3)

myliste.name+="CHANGE"之间有所不同。他们两个都创建一个新的s->s+="CHANGE"实例,但是第一个将新的String分配给String类的实例的实例变量(并因此对该实例进行突变),而第二个实例将其分配给本地Employee变量。

因此,String更改了原始e.name+="CHANGE"的对应实例,而List则没有更改。

答案 1 :(得分:1)

问题与流无关。

在以下lambda表达式:s -> s += "CHANGE"中,您只是在重新分配局部变量ss += "CHANGE"还返回连接的结果,这说明了为什么流显示映射的值。这种重新分配仅在lambda表达式的局部范围内有效。

但是e.name+="CHANGE"更新Employee对象e的字段。这将更新原始对象本身。

您应该收集映射值,而不是更新原始流元素。顺便说一句,在您的情况下,甚至无法选择更新原始流元素,因为您无法修改String对象。