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

Java作业:如何让TableauPartiel的子列表引用原ArrayList?

解决思路:让TableauPartiel成为原ArrayList的视图而非独立拷贝

你遇到的核心问题是之前的实现都创建了新的ArrayList实例,导致子列表和原列表完全独立。要实现修改子列表影响原列表的效果,我们需要让TableauPartiel本身作为原ArrayList的一个视图——也就是共享同一个底层数组,只是通过偏移量来限制访问的范围。

具体实现方案

我们需要给TableauPartiel添加两个额外的成员变量,用来标记当前视图在原ArrayList中的起始和结束索引,所有操作都基于原列表的引用进行索引转换。

完整代码示例

import java.util.ArrayList;

class CoupeDeA {
    private final int begin;
    private final int end;

    public CoupeDeA(int begin, int end) {
        this.begin = begin;
        this.end = end;
    }

    public int getBegin() {
        return begin;
    }

    public int getEnd() {
        return end;
    }
}

public class TableauPartiel<E> {
    // 共享的原ArrayList引用
    private final ArrayList<E> originalTableau;
    // 当前视图在原列表中的起始和结束索引(左闭右开规则)
    private final int viewBegin;
    private final int viewEnd;

    // 从数组初始化的构造方法:创建完整视图
    public TableauPartiel(E[] arr) {
        originalTableau = new ArrayList<>();
        for (E element : arr) {
            originalTableau.add(element);
        }
        viewBegin = 0;
        viewEnd = originalTableau.size();
    }

    // 内部构造方法:用于创建子视图,对外隐藏
    private TableauPartiel(ArrayList<E> original, int begin, int end) {
        this.originalTableau = original;
        this.viewBegin = begin;
        this.viewEnd = end;
    }

    // 获取当前视图的元素数量
    public int size() {
        return viewEnd - viewBegin;
    }

    // 获取视图中指定索引的元素
    public E get(int index) {
        if (index < 0 || index >= size()) {
            throw new IndexOutOfBoundsException("Index out of bounds: " + index);
        }
        // 转换为原列表的真实索引
        return originalTableau.get(viewBegin + index);
    }

    // 修改视图中指定索引的元素
    public void set(int index, E element) {
        if (index < 0 || index >= size()) {
            throw new IndexOutOfBoundsException("Index out of bounds: " + index);
        }
        // 转换为原列表的真实索引并修改
        originalTableau.set(viewBegin + index, element);
    }

    // 实现coupe方法:返回原列表的子视图
    public TableauPartiel<E> coupe(CoupeDeA coupe) throws IndexOutOfBoundsException {
        int coupeBegin = coupe.getBegin();
        int coupeEnd = coupe.getEnd();

        // 验证截取范围在当前视图的合法范围内
        if (coupeBegin < 0 || coupeEnd > size() || coupeBegin > coupeEnd) {
            throw new IndexOutOfBoundsException("Invalid coupe range: [" + coupeBegin + ", " + coupeEnd + ")");
        }

        // 计算在原列表中的真实起始和结束索引
        int newBegin = viewBegin + coupeBegin;
        int newEnd = viewBegin + coupeEnd;

        // 创建并返回新的视图实例,共享原ArrayList
        return new TableauPartiel<>(originalTableau, newBegin, newEnd);
    }

    // 测试用的toString方法,方便查看内容
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < size(); i++) {
            sb.append(get(i));
            if (i != size() - 1) {
                sb.append(", ");
            }
        }
        sb.append("]");
        return sb.toString();
    }

    public static void main(String[] args) {
        Integer[] arr = {8,7,6,5};
        TableauPartiel<Integer> tab = new TableauPartiel<>(arr);
        System.out.println("原列表tab: " + tab); // 输出 [8, 7, 6, 5]

        // 截取索引1到3的子视图(左闭右开,对应原列表的7、6)
        TableauPartiel<Integer> tab2 = tab.coupe(new CoupeDeA(1, 3));
        System.out.println("子列表tab2: " + tab2); // 输出 [7, 6]

        // 修改子列表的索引1位置
        tab2.set(1, 45);
        System.out.println("修改后tab2: " + tab2); // 输出 [7, 45]
        System.out.println("修改后原列表tab: " + tab); // 输出 [8, 7, 45, 5],符合需求
    }
}

方案原理说明

  • 共享底层数据:所有TableauPartiel实例(包括原实例和子视图实例)都持有同一个originalTableau引用,没有创建新的ArrayList或拷贝元素。
  • 索引转换:每个实例通过viewBegin和viewEnd限制访问范围,get/set操作会自动将视图索引转换为原列表的真实索引。
  • 实时同步修改:修改子视图的元素本质是直接修改原ArrayList的对应位置,因此原实例会立刻看到变化。

对比你之前的实现

你之前的代码要么是创建新数组并拷贝元素(完全独立),要么是用subList(本质也是视图,但被老师禁止)。这个方案手动实现了类似subList的视图逻辑,但完全不依赖JDK的subList方法,完美符合要求。

内容的提问来源于stack exchange,提问作者Tanryoku

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:32:06