首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java SE 5.0 泛型集合開發指南:從 Queue 到可預覽 Stack 完整實作

     編輯:Java 相關知識

泛型類別設計基礎

J2SE 5.0 引入泛型,允許類別定義型別參數:

public class Example<ONE, TWO, THREE> {
    private ONE one; private TWO two; private THREE three;
    // getter/setter...
}

// 使用時具體化型別
Example<Double, Integer, String> ex = new Example<>();
ex.setOne(1.5); ex.setTwo(2); ex.setThree("Three");

關鍵點:型別擦除僅存在編譯期,執行期為原始類型;但編譯器提供型別安全保證。

實作一:泛型 Queue(先進先出)

public class Queue<T> {
    private List<T> list = new ArrayList<>();
    
    public void push(T obj) { list.add(obj); }
    
    public T pop() throws QueueException {
        if (list.isEmpty()) 
            throw new QueueException("Queue is empty");
        T result = list.remove(0);
        return result;
    }
    
    public boolean isEmpty() { return list.isEmpty(); }
    public int size() { return list.size(); }
    public void clear() { list.clear(); }
}

// 自訂例外
public class QueueException extends Exception {
    public QueueException(String msg) { super(msg); }
}

// 測試
Queue<Integer> q = new Queue<>();
q.push(1); q.push(2); q.push(3);  // 自動裝箱 int → Integer
System.out.println(q.pop());  // 1
System.out.println(q.pop());  // 2
System.out.println(q.pop());  // 3

實作二:可預覽 Stack(PeekableStack)支援 for-each 迭代

核心介面實作

public class PeekableStack<T> implements Iterable<T> {
    private List<T> list = new ArrayList<>();
    private int version = 0;  // 版本號偵測並發修改
    
    public void push(T obj) {
        list.add(obj);
        version++;
    }
    
    public T pop() {
        if (list.isEmpty()) return null;
        version++;
        return list.remove(list.size() - 1);
    }
    
    public T peek() {
        return list.isEmpty() ? null : list.get(list.size() - 1);
    }
    
    @Override
    public Iterator<T> iterator() {
        return new PeekableStackIterator<>(this, new ArrayList<>(list), version);
    }
    
    // 內部類別:快照式迭代器
    private static class PeekableStackIterator<T> implements Iterator<T> {
        private final List<T> snapshot;
        private final int expectedVersion;
        private int index = 0;
        
        PeekableStackIterator(PeekableStack<T> stack, List<T> snapshot, int version) {
            this.snapshot = snapshot;
            this.expectedVersion = version;
        }
        
        @Override
        public boolean hasNext() { return index < snapshot.size(); }
        
        @Override
        public T next() {
            // 可選:檢查並發修改
            return snapshot.get(index++);
        }
        
        @Override
        public void remove() { throw new UnsupportedOperationException(); }
    }
}

關鍵設計決策

決策點方案理由
迭代器實作快照模式 (Snapshot)避免 ConcurrentModificationException、支援多迭代器並存
版本號機制push/pop 遞增 version可選擇性檢查:建構迭代器時記錄 version,next() 時比對
實作 Iterable而非 Iterator支援 for-each 語法:for (T item : stack)
泛型傳播Iterator<T> 保持型別編譯期型別安全、無需轉型

測試驗證

PeekableStack<Integer> stack = new PeekableStack<>();
stack.push(1); stack.push(2); stack.push(3);

// for-each 迭代(不修改堆疊)
for (int i : stack) {
    System.out.println(i);  // 輸出 1, 2, 3 (底部到頂部)
}

// 正常堆疊操作
System.out.println("Pop: " + stack.pop());  // 3
System.out.println("Pop: " + stack.pop());  // 2
System.out.println("Pop: " + stack.pop());  // 1

與 Java Collections Framework 整合

為無縫整合,建議額外實作:

  • Collection<T> 介面:獲得 addAll、containsAll 等標準操作
  • Serializable:支援序列化
  • Cloneable:支援淺層複製
  • 提供 toArray() 方法

常見陷阱與最佳實踐

  1. 避免原始類型:永不使用 Queue q = new Queue(),會失去型別檢查
  2. 通配符靈活運用:<? extends T> (生產者)、<? super T> (消費者)
  3. 不可變物件優先:存入集合的物件最好不可變,避免外部修改破壞不變性
  4. 效能考量:頻繁頭部插入/刪除用 LinkedList、隨機存取用 ArrayList
  5. 文件化型別參數:JavaDoc 標註 @param <T> 元素型別

結語

J2SE 5.0 泛型與 for-each 徹底改變集合開發體驗。實作自訂集合只需:

  1. 類別宣告型別參數 <T>
  2. 內部儲存結構使用 List<T> 或 T[]
  3. 實作 Iterable<T> 支援 for-each
  4. 視需求實作 Collection<T> 獲得完整標準 API

如此即可享受編譯期型別安全、程式碼可讀性與零轉型的現代 Java 集合開發體驗。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved