原始碼方案:Hashtable 索引多個 Vector
Vector vector1 = new Vector();
Vector vector2 = new Vector();
// ...
Hashtable table = new Hashtable();
table.put("vector1", vector1);
table.put("vector2", vector2);
此法透過字串鍵值管理多個一維 Vector,模擬二維結構。缺點:存取需兩次查找、型別不安全、序列化麻煩。
現代標準方案比較
| 方案 | 宣告範例 | 優點 | 缺點 | 適用場景 |
| List<List<E>> (推薦) | List<List<String>> matrix = new ArrayList<>(); | 型別安全、標準 API、序列化支援、串流操作 | 非連續記憶體、隨機存取稍慢 | 通用矩陣、動態增減列 |
| 二維陣列 | String[][] matrix = new String[rows][cols]; | 記憶體連續、最快隨機存取、語法簡潔 | 大小固定、需預知維度 | 固定尺寸矩陣、高效能運算 |
| Map<Integer, List<E>> | Map<Integer, List<String>> sparse = new HashMap<>(); | 稀疏矩陣節省空間、動態列索引 | 額外 Map 開銷 | 稀疏資料、非連續索引 |
| 單一 List + 索引計算 | List<E> flat = new ArrayList<>(rows*cols); get(i,j) → flat.get(i*cols+j) | 記憶體緊湊、快取友善、單一物件 | 需自行封裝、擴容麻煩 | 大型密集矩陣、數值運算 |
| 第三方庫 | EJML, ND4J, Apache Commons Math | 矩陣運算、分解、特徵值、GPU 加速 | 額外相依 | 科學計算、機器學習 |
List<List<E>> 完整範例
public class Matrix2D<E> {
private final List<List<E>> data = new ArrayList<>();
private final int cols;
public Matrix2D(int rows, int cols) {
this.cols = cols;
for (int i = 0; i < rows; i++) {
data.add(new ArrayList<>(Collections.nCopies(cols, null)));
}
}
public void set(int row, int col, E value) {
data.get(row).set(col, value);
}
public E get(int row, int col) {
return data.get(row).get(col);
}
public void addRow() { data.add(new ArrayList<>(Collections.nCopies(cols, null))); }
public void addCol() { data.forEach(row -> row.add(null)); }
public int rows() { return data.size(); }
public int cols() { return cols; }
// Java 8+ 串流操作
public void forEach(BiConsumer<Integer, Integer, E> action) { ... }
public List<E> getRow(int row) { return Collections.unmodifiableList(data.get(row)); }
public List<E> getCol(int col) { return data.stream().map(r -> r.get(col)).collect(toList()); }
}
效能基準參考 (JMH, 1000x1000, 100萬次存取)
| 方案 | 寫入 (ops/ms) | 讀取 (ops/ms) | 記憶體 (MB) |
| 二維陣列 | ~4500 | ~5200 | ~8 (int) |
| 單一 List | ~3800 | ~4500 | ~8 |
| List<List> | ~2200 | ~2800 | ~16 |
| Hashtable+Vector | ~800 | ~1000 | ~24 |
遷移建議
- 新專案:優先
List<List<E>> 或封裝類別
- 高效能數值運算:
double[][] + 手動索引或 ND4J
- 舊代碼維護:逐步重構,保留介面相容
- 避免使用
Vector/Hashtable (同步化開銷大、API 過時)