用戶重複點擊按鈕向 ArrayList 添加相同項目 (如 "1 Whatever"),需合並為 "2 Whatever"。直接操作字符串列表脆弱、難維護、順序不穩,正確做法是領域建模:定義實體類,用 Map 聚合,再轉列表。
// ❌ 脆弱:依賴固定格式 "數字 名稱"、split 易出錯、順序丟失
if (list.contains(item)) {
String[] parts = item.split(" ");
int count = Integer.parseInt(parts[0]) + 1;
list.remove(item);
list.add(count + " " + parts[1]);
}
// 1. 定義實體類 (不可變、Equals/HashCode 基於 name)
public class CartItem {
private final String name;
private int count;
private final String spec; // 規格
private final double price; // 單價
public CartItem(String name, String spec, double price) {
this.name = name;
this.spec = spec;
this.price = price;
this.count = 1;
}
public void increment() { count++; }
public String getDisplayText() { return count + " " + name + " - " + spec; }
// Getters, equals/hashCode 基於 name+spec
}
// 2. 使用 Map 聚合 (O(1) 查找)
Map itemMap = new LinkedHashMap<>(); // 保持插入順序
// 點擊按鈕添加
public void addItem(String name, String spec, double price) {
String key = name + "|" + spec; // 唯一鍵
CartItem item = itemMap.get(key);
if (item == null) {
item = new CartItem(name, spec, price);
itemMap.put(key, item);
} else {
item.increment();
}
refreshListView(); // 通知適配器更新
}
// 3. 適配器使用 List (從 Map.values() 獲取)
List displayList = new ArrayList<>(itemMap.values());
adapter.updateData(displayList);
public class CartAdapter extends BaseAdapter {
private List items = new ArrayList<>();
private LayoutInflater inflater;
public void updateData(List newItems) {
this.items = newItems;
notifyDataSetChanged();
}
@Override public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.item_cart, parent, false);
holder = new ViewHolder(convertView);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
CartItem item = items.get(position);
holder.nameText.setText(item.getDisplayText());
holder.priceText.setText(String.format("¥%.2f", item.getPrice() * item.getCount()));
return convertView;
}
// ViewHolder 省略
}
class CartDiffCallback : DiffUtil.ItemCallback() {
override fun areItemsTheSame(old: CartItem, new: CartItem) = old.name == new.name && old.spec == new.spec
override fun areContentsTheSame(old: CartItem, new: CartItem) = old.count == new.count
}
// 提交列表
adapter.submitList(new ArrayList<>(itemMap.values()))
| 方案 | 查找複雜度 | 順序保持 | 擴展性 | 代碼量 |
|---|---|---|---|---|
| 字符串 List + split | O(n) | ❌ 丟失 | 極差 | 少 |
| ArrayList 遍歷查找 | O(n) | ✅ | 差 | 中 |
| Map | O(1) | ✅ (LinkedHashMap) | 優 | 中 |
| 數據庫 (Room/SQLite) | O(log n) | ✅ | 極佳 | 多 |
increment())、格式化 (getDisplayText())、業務規則。LinkedHashMap 或單獨維護順序列表。List,不處理合並邏輯。從「字符串拼接湊合」進化到「領域模型驅動」,是從初級到中級 Android 開發的關鍵轉折。