核心介面概覽
在 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。
常用方法速查
| 方法 | 用途 |
hasNextElement() | 是否有下一筆記錄 |
nextRecord() | 取得下一筆記錄位元組陣列 |
nextRecordId() | 取得下一筆記錄 ID |
previousRecord() | 取得上一筆記錄(雙向遍歷) |
numRecords() | 符合條件的記錄總數 |
reset() | 將游標重置至起始位置 |
destroy() | 釋放資源,用畢必須呼叫 |
三、完整資料實體與序列化: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()、並將篩選邏輯封裝於資料實體類別,能兼顧效能與程式碼可維護性。
- 上一篇文章: J2ME Record Management System 進階:Java IO 與自定義序列化實作
- 下一篇文章: 基於 MIDP 1.0 實作 RMS 容量偵測器:測試手機真實可用儲存空間
Copyright ©
程式碼之家 All Rights Reserved