自定义ArrayList如何实现与原列表联动的subList()方法
问题原因分析
你现在的实现之所以修改子列表无法同步到原列表,核心原因是你主动复制了原数组的元素到新数组,再用新数组生成独立List,新List和原列表没有绑定关系,修改操作只会作用于新数组,自然不会影响原列表。
解决方案
你确实需要额外实现一个内部的SubList类,这个类不单独存储数据,所有操作都直接代理到原列表实现,就能实现修改同步。
步骤1:在CustomArrayList内部实现SubList内部类
推荐继承AbstractList减少需要实现的方法量,示例代码如下:
public class CustomArrayList<T> { // 你原有的其他成员变量 private Object[] array; private int size; // 可选:和JDK实现对齐,新增modCount记录列表结构修改次数,避免并发修改问题 private int modCount = 0; private class SubList extends AbstractList<T> { private final CustomArrayList<T> parent; private final int offset; private int subSize; // 记录生成子列表时原列表的modCount,结构变更后操作子列表直接抛异常 private final int expectedModCount; SubList(CustomArrayList<T> parent, int fromIndex, int toIndex) { this.parent = parent; this.offset = fromIndex; this.subSize = toIndex - fromIndex; this.expectedModCount = parent.modCount; } @Override public T get(int index) { // 校验子列表索引合法性 if (index < 0 || index >= subSize) { throw new IndexOutOfBoundsException(); } // 校验原列表结构是否发生变化 checkForComodification(); // 直接取原列表对应偏移位置的元素 return parent.get(offset + index); } @Override public T set(int index, T element) { if (index < 0 || index >= subSize) { throw new IndexOutOfBoundsException(); } checkForComodification(); // 直接修改原列表对应位置的元素 return parent.set(offset + index, element); } @Override public int size() { checkForComodification(); return subSize; } @Override public void add(int index, T element) { if (index < 0 || index > subSize) { throw new IndexOutOfBoundsException(); } checkForComodification(); parent.add(offset + index, element); // 原列表结构变更,更新modCount和子列表长度 expectedModCount = parent.modCount; subSize++; } @Override public T remove(int index) { if (index < 0 || index >= subSize) { throw new IndexOutOfBoundsException(); } checkForComodification(); T removed = parent.remove(offset + index); expectedModCount = parent.modCount; subSize--; return removed; } private void checkForComodification() { if (parent.modCount != expectedModCount) { throw new ConcurrentModificationException(); } } } // 你原有的其他方法,注意在add/remove等修改结构的方法里modCount自增 }
注意:你原有的add、remove等会修改列表结构的方法,需要每次执行时对modCount执行自增操作,和JDK的ArrayList实现逻辑对齐。
步骤2:修改subList方法实现
删掉原来复制数组的逻辑,直接返回SubList实例即可:
public List<T> subList(int fromIndex, int toIndex) { if (fromIndex < 0 || toIndex > size() || fromIndex > toIndex) throw new IndexOutOfBoundsException(); return new SubList(this, fromIndex, toIndex); }
修改完成后运行你的测试用例,调用subList(1,4).set(0,12)时,会直接修改原列表索引1+0=1位置的元素,即可通过测试。
内容的提问来源于stack exchange,提问作者alqueen
相关产品推荐
相关产品推荐

