S SmartDocs
系列: Angelia java 53 行 · 更新於 2026-09-27

CircularBufferChatHistory.java

Angelia/Java/Week_6_7/code/02_adt_interfaces/CircularBufferChatHistory.java

/**
 * 實作一:固定容量的「環狀緩衝區」(circular buffer)。
 *
 * 只保留最近 capacity 則訊息;滿了之後,新訊息會覆蓋最舊的那一則。
 * 優點:空間固定 O(capacity)。缺點:舊訊息會遺失。
 *
 * 資料不變量:
 *   0 <= size <= arr.length
 *   0 <= nextAvailable < arr.length
 *   最新的訊息位於 (nextAvailable - 1 + arr.length) % arr.length
 */
public class CircularBufferChatHistory implements ChatHistory {

    private final String[] arr;      // 固定大小的儲存空間
    private int nextAvailable;       // 下一則訊息要寫入的索引
    private int size;                // 目前保存的訊息數量

    public CircularBufferChatHistory(int capacity) {
        if (capacity <= 0) {
            throw new IllegalArgumentException("容量必須為正數:" + capacity);
        }
        this.arr = new String[capacity];
        this.nextAvailable = 0;
        this.size = 0;
    }

    @Override
    public void addMessage(String msg) {
        this.arr[this.nextAvailable] = msg;
        // 取餘數讓索引「繞回」開頭:這就是「環狀」的由來
        this.nextAvailable = (this.nextAvailable + 1) % this.arr.length;
        if (this.size < this.arr.length) {
            this.size = this.size + 1;      // 還沒滿:數量 +1;滿了:數量維持不變(覆蓋)
        }
    }

    @Override
    public void display() {
        int i = 0;
        // 從最新的一則往回走
        int idx = (this.nextAvailable - 1 + this.arr.length) % this.arr.length;
        while (i < this.size) {
            System.out.println(this.arr[idx]);
            idx = (idx - 1 + this.arr.length) % this.arr.length;   // 往回退一格(可能繞回尾端)
            i = i + 1;
        }
    }

    @Override
    public int size() {
        return this.size;
    }
}

相關文章