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

Java 實現兼具 List 與 Map 特性的 ListMap 容器

     編輯:Java 相關知識

Java 集合框架中 List 維護插入順序並允許重複元素,Map 則鍵值唯一且支持快速鍵查找。某些業務場景需要同時擁有這兩者特性:既要按索引訪問,又要按鍵快速查找,還要保持插入順序。由於 Java 不允許類同時實現 List 和 Map 兩個接口,本文實現了一個自定義 ListMap<K, V> 容器類,融合雙重功能。

核心設計思路

  • 內部使用 List<Item> 存儲鍵值對,Item 為內部類封裝 key 和 value
  • 鍵唯一性由 put() 和 add() 方法通過遍歷檢查保證
  • 提供雙重訪問介面:get(index) 按位置取值,get(key) 按鍵取值
  • 衍生出 containsKey()、containsValue()、indexOfKey()、indexOfValue() 等專用方法

完整實現代碼

package myCollections;

import java.util.*;

/**
 * 兼具 List 和 Map 功能的容器類
 */
@SuppressWarnings({"unchecked"})
public class ListMap<K, V> {

    private List<Item> values = new ArrayList<>();

    // === 基礎屬性 ===
    public int size() { return values.size(); }
    public boolean isEmpty() { return values.isEmpty(); }

    // === 迭代與轉換 ===
    public Iterator<V> iterator() { return values().iterator(); }
    
    public V[] toArray() {
        Object[] arr = new Object[values.size()];
        for (int i = 0; i < values.size(); i++) arr[i] = values.get(i).value;
        return (V[]) arr;
    }

    // === Map 風格查詢 ===
    public boolean containsKey(K key) {
        if (key == null) return false;
        for (Item item : values) if (item.key.equals(key)) return true;
        return false;
    }

    public boolean containsValue(V value) {
        for (Item item : values) if (item.value.equals(value)) return true;
        return false;
    }

    public V get(K key) {
        for (Item item : values) if (item.key.equals(key)) return item.value;
        return null;
    }

    public V put(K key, V value) {
        for (Item item : values) {
            if (item.key.equals(key)) {
                V replaced = item.value;
                item.value = value;
                return replaced;
            }
        }
        values.add(new Item(key, value));
        return null;
    }

    public boolean remove(K key) {
        for (Item item : values) {
            if (item.key.equals(key)) return values.remove(item);
        }
        return false;
    }

    // === List 風格操作 ===
    public V remove(int index) { return values.remove(index).value; }
    public void clear() { values.clear(); }
    public V get(int index) { return values.get(index).value; }
    public V set(int index, V value) {
        Item item = values.get(index);
        V old = item.value;
        item.value = value;
        return old;
    }

    public void add(int index, K key, V value) {
        if (containsKey(key)) throw new IllegalStateException("key already exists.");
        values.add(index, new Item(key, value));
    }

    // === 索引查找 ===
    public int indexOfValue(V value) {
        for (int i = 0; i < values.size(); i++)
            if (values.get(i).value.equals(value)) return i;
        return -1;
    }

    public int indexOfKey(K key) {
        if (key == null) return -1;
        for (int i = 0; i < values.size(); i++)
            if (values.get(i).key.equals(key)) return i;
        return -1;
    }

    // === 子列表與視圖 ===
    public ListMap<K, V> subList(int fromIndex, int toIndex) {
        ListMap<K, V> map = new ListMap<>();
        map.values.addAll(values.subList(fromIndex, toIndex));
        return map;
    }

    public List<V> values() {
        List<V> list = new ArrayList<>();
        for (Item item : values) list.add(item.value);
        return list;
    }

    public List<K> keys() {
        List<K> list = new ArrayList<>();
        for (Item item : values) list.add(item.key);
        return list;
    }

    // === 排序與反轉 ===
    public void sortKey() {
        Collections.sort(values, (i1, i2) -> {
            Comparable c1 = (Comparable) i1.key, c2 = (Comparable) i2.key;
            if (c1 == null && c2 == null) return 0;
            if (c1 == null) return -1;
            if (c2 == null) return 1;
            return c1.compareTo(c2);
        });
    }

    public void sortValue() {
        Collections.sort(values, (i1, i2) -> {
            Comparable c1 = (Comparable) i1.value, c2 = (Comparable) i2.value;
            if (c1 == null && c2 == null) return 0;
            if (c1 == null) return -1;
            if (c2 == null) return 1;
            return c1.compareTo(c2);
        });
    }

    public void reverse() { Collections.reverse(values); }

    // === 內部類 ===
    private class Item {
        public K key;
        public V value;
        public Item(K key, V value) {
            if (key == null) throw new NullPointerException("key cannot be null.");
            this.key = key; this.value = value;
        }
    }
}

使用示例

ListMap<String, Integer> scores = new ListMap<>();
scores.put("Alice", 95);
scores.put("Bob", 87);
scores.add(0, "Charlie", 92); // 插入到頭部

System.out.println(scores.get(0));      // 92 (按索引)
System.out.println(scores.get("Bob"));  // 87 (按鍵)
System.out.println(scores.indexOfKey("Alice")); // 1

scores.sortKey(); // 按鍵排序
scores.sortValue(); // 按值排序

性能特徵與適用場景

操作時間複雜度說明
按鍵查找/插入/刪除O(n)需線性掃描
按索引查找/修改O(1)ArrayList 隨機訪問
遍歷/迭代O(n)順序訪問

適用場景:數據量較小(<1000)、頻繁按順序遍歷且偶爾按鍵查找、需要保持插入順序的鍵值對集合。大數據量高頻鍵查找場景建議使用 LinkedHashMap + 獨立 ArrayList 組合。

潛在改進點

  • 引入 HashMap<K, Integer> 緩存鍵到索引映射,將鍵操作優化至 O(1)
  • 實現 Collection<V> 和 Map<K, V> 接口以兼容標準庫
  • 添加并發安全版本(Collections.synchronizedList 或 CopyOnWriteArrayList)

這個 ListMap 實現雖簡單,卻精準解決了「有序鍵值對」這一特定需求,是理解集合框架設計權衡的優秀案例。

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