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

RMS 進階查詢與遍歷:RecordFilter 與 RecordEnumeration 實戰詳解

     編輯:J2ME

核心介面概覽

在 Record Management System (RMS) 中,RecordFilter 與 RecordEnumeration 是實現條件篩選、排序與高效遍歷的兩大核心介面。本文透過完整的通訊錄範例,示範如何靈活運用這兩者。

一、RecordFilter:精準篩選記錄

介面定義

public interface RecordFilter {
    boolean matches(byte[] recordData);
}

實作此介面並覆寫 matches() 方法,即可自訂篩選邏輯。常見做法是將其寫為內部類別,捕獲外部查詢關鍵字。

實作範例:依使用者名稱篩選

private static class RecordEntryFilter implements RecordFilter {
    private String key; // 查詢關鍵字

    public RecordEntryFilter(String key) {
        this.key = key;
    }

    public boolean matches(byte[] data) {
        try {
            // 委派給資料實體類別的靜態比對方法
            return RecordEntry.matches(data, key);
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }
}

二、RecordEnumeration:高效遍歷與雙向游標

取得枚舉器

RecordEnumeration records = rs.enumerateRecords(
    new RecordEntryFilter("ming"), // Filter
    null,                          // Comparator,null 表示依預設順序(Record ID 遞增)
    false                          // keepUpdated:false 為效能優先,不即時追蹤資料變更
);

關鍵參數說明:

  • RecordFilter:篩選條件。
  • RecordComparator:排序規則,可為 null。
  • keepUpdated:設為 true 會即時反映 RMS 變更,但效能開銷極大,建議預設 false。

常用方法速查

三、完整資料實體與序列化:RecordEntry

public class RecordEntry {
    private String userName;
    private String phoneNum;

    // 建構子、Getter/Setter 略...

    // 序列化
    public byte[] serialize() throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);
        dos.writeUTF(userName);
        dos.writeUTF(phoneNum);
        return baos.toByteArray();
    }

    // 反序列化
    public static RecordEntry deserialize(byte[] data) throws IOException {
        ByteArrayInputStream bais = new ByteArrayInputStream(data);
        DataInputStream dis = new DataInputStream(bais);
        RecordEntry entry = new RecordEntry();
        entry.userName = dis.readUTF();
        entry.phoneNum = dis.readUTF();
        return entry;
    }

    // 供 Filter 呼叫的比對邏輯:比對 userName
    public static boolean matches(byte[] data, String key) throws IOException {
        ByteArrayInputStream bais = new ByteArrayInputStream(data);
        DataInputStream dis = new DataInputStream(bais);
        return dis.readUTF().equals(key); // 精確比對;若需前綴比對可改用 startsWith()
    }

    public String toString() {
        return userName + ":" + phoneNum;
    }
}

四、資料存取模型:RecordModel

封裝 RMS 操作,提供初始化資料、關鍵字查詢等功能:

public class RecordModel {
    private RecordStore rs;
    private static final String STORE_NAME = "address_book";
    private RecordEntry[] initData = {
        new RecordEntry("ming", "12345"),
        new RecordEntry("pain", "123456"),
        new RecordEntry("Linux", "234566"),
        new RecordEntry("mingtian", "3456677")
    };

    public RecordModel() throws RecordStoreException {
        rs = RecordStore.openRecordStore(STORE_NAME, true);
        if (rs.getNumRecords() == 0) init(); // 僅首次寫入測試資料
    }

    private void init() {
        try {
            for (RecordEntry entry : initData) {
                rs.addRecord(entry.serialize(), 0, entry.serialize().length);
            }
        } catch (IOException | RecordStoreException e) {
            e.printStackTrace();
        }
    }

    // 關鍵字查詢,回傳符合條件的 RecordEntry 陣列
    public RecordEntry[] getRecord(String key) {
        try {
            if (rs.getNumRecords() == 0) return new RecordEntry[0];

            RecordEnumeration enum = rs.enumerateRecords(
                new RecordEntryFilter(key), null, false
            );
            int count = enum.numRecords();
            if (count == 0) return new RecordEntry[0];

            RecordEntry[] result = new RecordEntry[count];
            for (int i = 0; i < count; i++) {
                int id = enum.nextRecordId();
                byte[] data = rs.getRecord(id);
                result[i] = RecordEntry.deserialize(data);
            }
            enum.destroy(); // 釋放枚舉器資源
            return result;
        } catch (RecordStoreException | IOException e) {
            e.printStackTrace();
            return new RecordEntry[0];
        }
    }
}

五、MIDlet 整合測試

public class RecordFilterMIDlet extends MIDlet implements ItemStateListener {
    private Display display;
    private Form mainForm;
    private TextField inputField;
    private RecordModel model;

    protected void startApp() {
        display = Display.getDisplay(this);
        mainForm = new Form("通訊錄查詢");
        model = new RecordModel();
        inputField = new TextField("輸入姓名:", "", 20, TextField.ANY);
        mainForm.append(inputField);
        mainForm.setItemStateListener(this);
        display.setCurrent(mainForm);
    }

    public void itemStateChanged(Item item) {
        if (item == inputField) {
            String keyword = inputField.getString();
            RecordEntry[] results = model.getRecord(keyword);
            if (results.length == 0) {
                System.out.println("查無資料");
            } else {
                for (RecordEntry e : results) {
                    System.out.println(e); // 輸出至控制台,實際應用可顯示於 List 或 Form
                }
            }
        }
    }
    // pauseApp, destroyApp 略...
}

六、進階提示:支援前綴比對

若需實現「通訊錄式」前綴搜尋(如輸入 "min" 找到 "ming"、"mingtian"),可擴充 RecordEntryFilter 建構子加入 type 參數,並在 RecordEntry.matches() 中依型別切換 equals() 或 startsWith() 邏輯。

小結

RecordFilter + RecordEnumeration 組合提供了類似 SQL WHERE + CURSOR 的查詢能力,是 RMS 開發中不可或缺的利器。善用 keepUpdated=false、及時呼叫 destroy()、並將篩選邏輯封裝於資料實體類別,能兼顧效能與程式碼可維護性。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方法用途
hasNextElement()是否有下一筆記錄
nextRecord()取得下一筆記錄位元組陣列
nextRecordId()取得下一筆記錄 ID
previousRecord()取得上一筆記錄(雙向遍歷)
numRecords()符合條件的記錄總數
reset()將游標重置至起始位置
destroy()釋放資源,用畢必須呼叫