You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 21:57:50