subList返回原列表的视图而非副本,修改双向同步;索引需满足0≤fromIndex≤toIndex≤size;不支持add、remove等结构性操作;多线程下不安全,需转不可变副本或加锁。
Java中的subList是List接口提供的一个视图方法,返回原列表的“活”子区间,不是独立副本——修改子列表会同步影响原列表,反之亦然。
调用 list.subList(fromIndex, toIndex) 得到的仍是同一个底层数据结构的引用。它不复制元素,只是定义了一个逻辑窗口。
ConcurrentModificationException,尤其在遍历时)UnsupportedOperationException或异常new ArrayList(list.subList(1, 4))
参数 fromIndex 和 toIndex 必须满足:0 ≤ fromIndex ≤ toIndex ≤ list.size(),否则抛IndexOutOfBoundsException。
fromIndex == toIndex 返回空子列表(长度为0,但非null)toIndex 取不到,即子列表包含索引 fromIndex 到 toIndex - 1 的元素subList(0, list.size()) 想复制全量——虽不报错,但仍是视图;应改用 new ArrayList(list)
因为子列表无法保证自身长度不变(受原列表约束),以下方法会抛出异常:
add(E)、addAll(Collection)、remove(Object)、removeAll(...) 等结构性修改方法(除非底层实现允许,如ArrayList子列表允许add/remove,但有严格位置限制)clear() 在某些JDK版本中可能被禁止(取决于具体List实现)get()、set()、contains()、indexOf()、iterator()(但迭代中修改原列表仍危险)subList本身不是线程安全的,且与原列表共享内部数组或节点。并发读写极易引发数据不一致或异常。
Lists.newArrayList(list.subList(a, b))(Guava)或 List.copyOf(list.subList(a, b))(Java 10+)Collections.unmodifiableList(
)包装子列表,防止意外修改基本上就这些。subList用起来简洁,但本质脆弱——理解它是“视图”而非“副本”,就能避开绝大多数坑。