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

Android ArrayList 合並重複項目:按名稱聚合計數的最佳實踐

     編輯:程式設計綜合問答

用戶重複點擊按鈕向 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]);
}

正確方案:領域模型 + Map 聚合


// 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 省略
}

進階:使用 RecyclerView + DiffUtil (現代標準)


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 + splitO(n)❌ 丟失極差少
ArrayList 遍歷查找O(n)✅差中
Map 聚合O(1)✅ (LinkedHashMap)優中
數據庫 (Room/SQLite)O(log n)✅極佳多

核心原則

  1. 數據結構決定演算法:聚合場景天然適合 Map/字典。
  2. 領域建模優於字符串處理:實體類封裝行為 (increment())、格式化 (getDisplayText())、業務規則。
  3. 保持插入順序:用 LinkedHashMap 或單獨維護順序列表。
  4. UI 只渲染模型:適配器接收 List,不處理合並邏輯。

從「字符串拼接湊合」進化到「領域模型驅動」,是從初級到中級 Android 開發的關鍵轉折。

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