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

Java泛型Table类getColumn方法实现求助:需返回可修改原表的引用

解决方案

首先可以明确:你现有的类属性List<List<E>> table和构造方法是完全符合需求的——用嵌套列表存储表格数据,构造方法正确初始化了每行并填充null,getRow直接返回原行的引用,修改返回值能同步原表,这部分逻辑没问题。

接下来重点解决getColumn的核心问题:要让返回的列表修改能同步原表,不能返回独立的新列表,而是要创建一个代理列表(Proxy List)——它不存储自身数据,所有读写操作都直接映射到原表格的对应列上。

完整实现代码

import java.util.*;

public class Table<E> {
    private List<List<E>> table;

    public Table(int rows, int columns) {
        this.table = new ArrayList<>();
        // 用Collections.nCopies简化行初始化,效果和嵌套循环一致
        for (int i = 0; i < rows; i++) {
            List<E> row = new ArrayList<>(Collections.nCopies(columns, null));
            table.add(row);
        }
    }

    // 返回原行引用,修改返回值同步原表
    public List<E> getRow(int rowIndex) {
        checkRowIndex(rowIndex);
        return table.get(rowIndex);
    }

    // 返回代理列列表,修改返回值同步原表
    public List<E> getColumn(int columnIndex) {
        checkColumnIndex(columnIndex);
        return new ColumnList(columnIndex);
    }

    // 获取表格行数
    public int rows() {
        return table.size();
    }

    // 获取表格列数
    public int columns() {
        return table.isEmpty() ? 0 : table.get(0).size();
    }

    // 私有方法:检查行索引合法性
    private void checkRowIndex(int rowIndex) {
        if (rowIndex < 0 || rowIndex >= rows()) {
            throw new IndexOutOfBoundsException("行索引越界: " + rowIndex);
        }
    }

    // 私有方法:检查列索引合法性
    private void checkColumnIndex(int columnIndex) {
        if (columnIndex < 0 || columnIndex >= columns()) {
            throw new IndexOutOfBoundsException("列索引越界: " + columnIndex);
        }
    }

    // 自定义代理列表,映射表格的某一列
    private class ColumnList implements List<E> {
        private final int columnIndex;

        public ColumnList(int columnIndex) {
            this.columnIndex = columnIndex;
        }

        @Override
        public E get(int rowIndex) {
            checkRowIndex(rowIndex);
            return table.get(rowIndex).get(columnIndex);
        }

        @Override
        public E set(int rowIndex, E element) {
            checkRowIndex(rowIndex);
            return table.get(rowIndex).set(columnIndex, element);
        }

        @Override
        public int size() {
            return rows();
        }

        // 以下是表格列不需要的操作,直接抛出不支持异常
        @Override
        public boolean isEmpty() {
            return rows() == 0;
        }

        @Override
        public boolean contains(Object o) {
            throw new UnsupportedOperationException("列不支持contains操作");
        }

        @Override
        public Iterator<E> iterator() {
            return new Iterator<>() {
                private int currentRow = 0;

                @Override
                public boolean hasNext() {
                    return currentRow < rows();
                }

                @Override
                public E next() {
                    if (!hasNext()) throw new NoSuchElementException();
                    return get(currentRow++);
                }
            };
        }

        @Override
        public Object[] toArray() {
            Object[] array = new Object[rows()];
            for (int i = 0; i < rows(); i++) {
                array[i] = get(i);
            }
            return array;
        }

        @Override
        public <T> T[] toArray(T[] a) {
            if (a.length < rows()) {
                a = (T[]) Arrays.copyOf(a, rows());
            }
            for (int i = 0; i < rows(); i++) {
                a[i] = (T) get(i);
            }
            if (a.length > rows()) a[rows()] = null;
            return a;
        }

        // 所有修改表格结构的操作都抛出异常,因为表格是固定行列的
        @Override
        public boolean add(E e) {
            throw new UnsupportedOperationException("固定大小表格的列不支持add操作");
        }

        @Override
        public boolean remove(Object o) {
            throw new UnsupportedOperationException("固定大小表格的列不支持remove操作");
        }

        @Override
        public boolean containsAll(Collection<?> c) {
            throw new UnsupportedOperationException("列不支持containsAll操作");
        }

        @Override
        public boolean addAll(Collection<? extends E> c) {
            throw new UnsupportedOperationException("固定大小表格的列不支持addAll操作");
        }

        @Override
        public boolean addAll(int index, Collection<? extends E> c) {
            throw new UnsupportedOperationException("固定大小表格的列不支持addAll操作");
        }

        @Override
        public boolean removeAll(Collection<?> c) {
            throw new UnsupportedOperationException("固定大小表格的列不支持removeAll操作");
        }

        @Override
        public boolean retainAll(Collection<?> c) {
            throw new UnsupportedOperationException("固定大小表格的列不支持retainAll操作");
        }

        @Override
        public void clear() {
            throw new UnsupportedOperationException("固定大小表格的列不支持clear操作");
        }

        @Override
        public void add(int index, E element) {
            throw new UnsupportedOperationException("固定大小表格的列不支持add操作");
        }

        @Override
        public E remove(int index) {
            throw new UnsupportedOperationException("固定大小表格的列不支持remove操作");
        }

        @Override
        public int indexOf(Object o) {
            throw new UnsupportedOperationException("列不支持indexOf操作");
        }

        @Override
        public int lastIndexOf(Object o) {
            throw new UnsupportedOperationException("列不支持lastIndexOf操作");
        }

        @Override
        public ListIterator<E> listIterator() {
            throw new UnsupportedOperationException("列不支持listIterator操作");
        }

        @Override
        public ListIterator<E> listIterator(int index) {
            throw new UnsupportedOperationException("列不支持listIterator操作");
        }

        @Override
        public List<E> subList(int fromIndex, int toIndex) {
            throw new UnsupportedOperationException("列不支持subList操作");
        }
    }
}

核心逻辑说明

  1. 代理列表ColumnList:
    • 它持有原Table的引用和目标列索引,所有get/set操作都会直接作用于原表格的对应位置(table.get(rowIndex).get(columnIndex)和table.get(rowIndex).set(columnIndex, element)),因此修改返回的ColumnList会同步修改原表。
    • 对于固定行列表格不需要的结构修改操作(如add/remove),直接抛出UnsupportedOperationException,符合表格的设计逻辑。
  2. 健壮性优化:添加了索引合法性检查,避免越界访问;用Collections.nCopies简化了行初始化代码。

测试验证示例

public class TestTable {
    public static void main(String[] args) {
        Table<String> table = new Table<>(3, 2);
        // 修改行数据
        table.getRow(0).set(0, "A");
        table.getRow(0).set(1, "B");
        // 修改列数据
        List<String> column1 = table.getColumn(1);
        column1.set(1, "C");
        column1.set(2, "D");

        // 打印验证结果
        for (int i = 0; i < table.rows(); i++) {
            System.out.println(table.getRow(i));
        }
        // 输出:
        // [A, B]
        // [null, C]
        // [null, D]
    }
}

内容的提问来源于stack exchange,提问作者Володимир Кельбель

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:37:55