Карта потока Java изменяет пользовательский объект класса, не встроенный в классы - PullRequest
0 голосов
/ 27 сентября 2018
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;
    }
}

Inside 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, но при изменении ArrayList из String значения не отражаются в исходном ArrayList.

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Проблема не имеет ничего общего с потоками.

В этом лямбда-выражении: s -> s += "CHANGE" вы просто переназначаете локальную переменную s.s += "CHANGE" также возвращает результат объединения, и это объясняет, почему поток показывает сопоставленное значение.Это переназначение действует только в локальной области действия лямбда-выражения.

Но e.name+="CHANGE" обновляет поле Employee объекта e.Это обновляет сам исходный объект.

Вы должны собирать сопоставленные значения вместо обновления исходных элементов потока.Кстати, обновление оригинальных потоковых элементов в вашем случае даже не вариант, потому что вы не можете изменять объекты String.

0 голосов
/ 27 сентября 2018

Существует разница между e.name+="CHANGE" и s->s+="CHANGE".Оба они создают новый экземпляр String, но в то время как первый назначает этот новый String переменной экземпляра экземпляра класса Employee (и, следовательно, изменяет этот экземпляр), второй назначает его локальному String переменная.

Поэтому e.name+="CHANGE" изменяет соответствующий экземпляр оригинала List, а s->s+="CHANGE" - нет.

...