我正在使用 Java
Stream
和 distinct()
测试一些东西,我遇到了一个场景,如果我在执行 Stream
后更改 distinct()
的对象,则执行的最终结果包含重复的项目。
在
distinct()
最终确定之前,对象进入下一个操作是否有意义?如何在不迭代整个列表的情况下保证唯一性?
OBS:Lombok:
@Data
注释在Dto类中添加了@EqualsAndHashCode
,它将自动生成equals()
和hashCode()
方法!
package br.com.marcusvoltolim;
import lombok.AllArgsConstructor;
import lombok.Data;
import reactor.core.publisher.Flux;
import java.util.*;
import java.util.stream.Collectors;
@Data
@AllArgsConstructor
class Dto {
private Long id;
}
public class Main {
public static void main(String[] args) {
Dto dto0 = new Dto(0L);
Dto dto1 = new Dto(1L);
Dto dto2 = new Dto(1L);
List<Dto> list = Arrays.asList(dto0, dto1, dto2);
System.out.println("Original list: " + list);
System.out.println("List with only distinct: " + list.stream().distinct().collect(Collectors.toList()));
List<Dto> streamList = list.stream()
.distinct()
.map(dto -> {
if (dto.getId() == 1L) {
dto.setId(3L);
}
return dto;
})
.collect(Collectors.toList());
System.out.println("Java Stream with map after distinct: " + streamList);
}
}
结果:
Original list: [Dto(id=0), Dto(id=1), Dto(id=1)]
List with only distinct: [Dto(id=0), Dto(id=1)]
Java Stream with map after distinct: [Dto(id=0), Dto(id=3), Dto(id=3)]
我期待的结果:
[Dto(id=0), Dto(id=3)]
要获得“预期”行为,您无法更改列表中列表元素的值。
你有:
if (dto.getId() == 1L) {
dto.setId(3L); // <--- Changing the contents
}
所以你正在改变节点的值和“等于”。
为了让它正常工作,你必须真正映射而不是修改:
if (dto.getId() == 1L) {
return new Dto(3L); // <--- Map to new object
} else {
return new Dto(dto.getId()); // <--- Map to new object
}