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操作"); } } }
核心逻辑说明
- 代理列表
ColumnList:- 它持有原
Table的引用和目标列索引,所有get/set操作都会直接作用于原表格的对应位置(table.get(rowIndex).get(columnIndex)和table.get(rowIndex).set(columnIndex, element)),因此修改返回的ColumnList会同步修改原表。 - 对于固定行列表格不需要的结构修改操作(如
add/remove),直接抛出UnsupportedOperationException,符合表格的设计逻辑。
- 它持有原
- 健壮性优化:添加了索引合法性检查,避免越界访问;用
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,提问作者Володимир Кельбель
相关产品推荐
相关产品推荐

