集合 一 实现一个map

1、使用关联数组实现一个键值对数量固定map

// 关联数组实现一个map,map数据结构:[[key0,value0],[key1,value1]]
class ArrayMap<K,V>{
    private Object[][] pairs;
    private int index;

    //新建map,须指定map的键值对数量
    public ArrayMap(int length) {
        pairs = new Object[length][2];
    }

    public void put(K key, V value) {
        if(index >= pairs.length)
            throw new ArrayIndexOutOfBoundsException();

        //put到map中的键值对,用数组存起来。[[key0,value0],[key1,value1]]
        pairs[index++] = new Object[]{ key, value };
    }

    public V get(K key) {
        for(int i = 0; i < index; i++)
            if(key.equals(pairs[i][0]))
                return (V)pairs[i][1];
        return null;
    }
}

class ArrayMapTest{
    public static void main(String[] args) {
        ArrayMap<String, String> map = new ArrayMap<String, String>(2);
        map.put("key1", "value1");
        map.put("key2", "value2");
        try {
            map.put("key3", "value3"); // 添加的键值对超过map的存储容量
        } catch(RuntimeException e) {
            print("Too many objects!\n");
        }
        System.out.println(map.get("key1"));
    }
}

2、用两个List实现map

// 用两个List实现map,结构如下:
// [key1, key2, key3]
// [val1, val2, val3]
class ListMap<K,V>{

    //keys存储key
    private List<K> keys = new ArrayList<K>();
    //values存储value
    private List<V> values = new ArrayList<V>();

    public V put(K key, V value) {
        if(key == null)
            throw new NullPointerException();

        V oldValue = get(key);
        if(!keys.contains(key)) {
            keys.add(key);
            values.add(value);
        } else{
            values.set(keys.indexOf(key), value);
        }

        return oldValue;
    }

    public V get(Object key) {
        if(key == null)
            throw new NullPointerException();

        if(!keys.contains(key))
            return null;

        //map的key在keys中的下标,就是对应value在values中的下标
        return values.get(keys.indexOf(key));
    }

}

class ListMapTest{
    public static void main(String[] args) {
        ListMap<String, String> map = new ListMap<String, String>();
        map.put("key1", "value1");
        map.put("key2", "value2");
        map.put("key3", "value3");
        System.out.println(map.get("key3"));
    }
}

3、使用散列提升查询速度

//map中的每一个键值都是一个Map.Entry,我们可以实现一个自己的MapEntry
class MapEntry<K,V> implements Map.Entry<K,V> {
    private K key;
    private V value;
    public MapEntry(K key, V value) {
        this.key = key;
        this.value = value;
    }
    public K getKey() { return key; }
    public V getValue() { return value; }
    public V setValue(V v) {
        V result = value;
        value = v;
        return result;
    }

    public int hashCode() {
        return (key==null ? 0 : key.hashCode()) ^
            (value==null ? 0 : value.hashCode());
    }
    public boolean equals(Object o) {
        if(!(o instanceof MapEntry)) return false;
        MapEntry me = (MapEntry)o;
        return
            (key == null ?
                me.getKey() == null : key.equals(me.getKey())) &&
                (value == null ?
                    me.getValue()== null : value.equals(me.getValue()));
    }
    public String toString() { return key + "=" + value; }
}


class SimpleHashMap<K,V> extends AbstractMap<K,V> {

    static final int SIZE = 997;
    //map的底层是数组,数组长度为997。buckets中的元素称为槽或桶,buckets有997个槽
    LinkedList<MapEntry<K,V>>[] buckets = new LinkedList[SIZE];

    public V put(K key, V value) {
        V oldValue = null;
        //对key的hashcode取模,决定此key-value存储到数组的哪个槽中
        int index = Math.abs(key.hashCode()) % SIZE;
        //槽是LinkedList类型,存储MapEntry这种key-value数据
        if(buckets[index] == null)
            buckets[index] = new LinkedList<MapEntry<K,V>>();

        LinkedList<MapEntry<K,V>> bucket = buckets[index];
        MapEntry<K,V> pair = new MapEntry<K,V>(key, value);
        boolean found = false;
        ListIterator<MapEntry<K,V>> it = bucket.listIterator();
        while(it.hasNext()) {
            MapEntry<K,V> iPair = it.next();
            if(iPair.getKey().equals(key)) {
                oldValue = iPair.getValue();
                it.set(pair);
                found = true;
                break;
            }
        }
        //未找到put进来的key-value,则在槽末尾添加key-value
        if(!found)
            buckets[index].add(pair);
        return oldValue;
    }
    public V get(Object key) {
        //get操作也对key的hashcode取模,确定在哪个槽中搜索key的对应的值
        int index = Math.abs(key.hashCode()) % SIZE;
        if(buckets[index] == null) return null;
        for(MapEntry<K,V> iPair : buckets[index])
            if(iPair.getKey().equals(key))
                return iPair.getValue();
        return null;
    }

    //这有bug,仅作为演示,返回的是map键值对的副本,不是map中原有的值,对返回结果读取操作没问题,但是赋值操作将不起效果
    //java源码的entrySet是通过视图实现的。
    public Set<Map.Entry<K,V>> entrySet() {
        Set<Map.Entry<K,V>> set= new HashSet<Map.Entry<K,V>>();
        for(LinkedList<MapEntry<K,V>> bucket : buckets) {
            if(bucket == null) continue;
            for(MapEntry<K,V> mpair : bucket)
                set.add(mpair);
        }
        return set;
    }

}



class SimpleHashMapTest{

    public static void main(String[] args) {
        SimpleHashMap<String,String> m = new SimpleHashMap<String,String>();
        m.put("key1", "value1");
        System.out.println(m);
        System.out.println(m.get("key1"));
        System.out.println(m.entrySet());
    }
}

SimpleHashMap的数据结构如下图

发布了51 篇原创文章 · 获赞 14 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u010606397/article/details/81231450