Java 21中更新ArrayList单个元素时全列表同步更新问题
问题根源:
Collections.nCopies导致所有Node实例共享同一引用 你遇到的问题核心出在lazy列表的初始化方式上:
this.lazy = new ArrayList<>(Collections.nCopies(4 * obj.size(), new Node(0, 0, 0)));
Collections.nCopies的工作逻辑是:创建一个包含指定数量元素的列表,但所有元素都是同一个对象的引用——你只调用了一次new Node(0,0,0),所以整个lazy列表里的所有"元素"其实都是指向这个唯一的Node实例。不管你通过lazy.get(index)获取哪个位置的元素,修改它的value本质上都是在修改同一个对象,自然会出现"更新一个元素所有元素同步变化"的现象。
另外你的list列表初始化也存在同样的问题,只是还没触发到对应的场景而已。
解决方案:为每个位置创建独立的Node实例
替换Collections.nCopies的初始化方式,确保每个列表元素都是全新的Node对象:
方式1:循环创建(直观易懂)
SegmentTreeObject(List<Integer> obj) { int treeSize = 4 * obj.size(); // 初始化list this.list = new ArrayList<>(treeSize); for (int i = 0; i < treeSize; i++) { this.list.add(new Node(100, 100, 0)); } // 初始化lazy this.lazy = new ArrayList<>(treeSize); for (int i = 0; i < treeSize; i++) { this.lazy.add(new Node(0, 0, 0)); } this.original = new ArrayList<>(obj); this.size = obj.size(); }
方式2:Stream流生成(简洁)
import java.util.stream.Collectors; import java.util.stream.IntStream; // ... SegmentTreeObject(List<Integer> obj) { int treeSize = 4 * obj.size(); this.list = IntStream.range(0, treeSize) .mapToObj(i -> new Node(100, 100, 0)) .collect(Collectors.toList()); this.lazy = IntStream.range(0, treeSize) .mapToObj(i -> new Node(0, 0, 0)) .collect(Collectors.toList()); this.original = new ArrayList<>(obj); this.size = obj.size(); }
修改后,每个列表位置的Node都是独立的实例,调用updateNode只会修改对应位置的元素,不会影响其他元素。
内容的提问来源于stack exchange,提问作者Al3x4ndru1
相关产品推荐
相关产品推荐

