数据结构之Map

来源:互联网 发布:淘宝女装腔调 编辑:程序博客网 时间:2024/06/06 05:44

直接上JDK源码
Map<K,V>源代码

public interface Map {    int size();    boolean isEmpty();    boolean containsKey(Object key);    boolean containsValue(Object value);    V get(Object key);    V put(K key, V value);    V remove(Object key);    void putAll(Map m);    void clear();    Set keySet();    Collection values();    Set> entrySet();    interface Entry {        K getKey();        V getValue();        V setValue(V value);        boolean equals(Object o);        int hashCode();        public static , V> Comparator> comparingByKey() {            return (Comparator> & Serializable)                (c1, c2) -> c1.getKey().compareTo(c2.getKey());        }        public static > Comparator> comparingByValue() {            return (Comparator> & Serializable)                (c1, c2) -> c1.getValue().compareTo(c2.getValue());        }        public static  Comparator> comparingByKey(Comparator cmp) {            Objects.requireNonNull(cmp);            return (Comparator> & Serializable)                (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());        }        public static  Comparator> comparingByValue(Comparator cmp) {            Objects.requireNonNull(cmp);            return (Comparator> & Serializable)                (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());        }    }    boolean equals(Object o);    int hashCode();    default V getOrDefault(Object key, V defaultValue) {        V v;        return (((v = get(key)) != null) || containsKey(key))            ? v            : defaultValue;    }    default void forEach(BiConsumer action) {        Objects.requireNonNull(action);        for (Map.Entry entry : entrySet()) {            K k;            V v;            try {                k = entry.getKey();                v = entry.getValue();            } catch(IllegalStateException ise) {                // this usually means the entry is no longer in the map.                throw new ConcurrentModificationException(ise);            }            action.accept(k, v);        }    }    default void replaceAll(BiFunction function) {        Objects.requireNonNull(function);        for (Map.Entry entry : entrySet()) {            K k;            V v;            try {                k = entry.getKey();                v = entry.getValue();            } catch(IllegalStateException ise) {                // this usually means the entry is no longer in the map.                throw new ConcurrentModificationException(ise);            }            // ise thrown from function is not a cme.            v = function.apply(k, v);            try {                entry.setValue(v);            } catch(IllegalStateException ise) {                // this usually means the entry is no longer in the map.                throw new ConcurrentModificationException(ise);            }        }    }    default V putIfAbsent(K key, V value) {        V v = get(key);        if (v == null) {            v = put(key, value);        }        return v;    }    default boolean remove(Object key, Object value) {        Object curValue = get(key);        if (!Objects.equals(curValue, value) ||            (curValue == null && !containsKey(key))) {            return false;        }        remove(key);        return true;    }    default boolean replace(K key, V oldValue, V newValue) {        Object curValue = get(key);        if (!Objects.equals(curValue, oldValue) ||            (curValue == null && !containsKey(key))) {            return false;        }        put(key, newValue);        return true;    }    default V replace(K key, V value) {        V curValue;        if (((curValue = get(key)) != null) || containsKey(key)) {            curValue = put(key, value);        }        return curValue;    }    default V computeIfAbsent(K key,            Function mappingFunction) {        Objects.requireNonNull(mappingFunction);        V v;        if ((v = get(key)) == null) {            V newValue;            if ((newValue = mappingFunction.apply(key)) != null) {                put(key, newValue);                return newValue;            }        }        return v;    }    default V computeIfPresent(K key,            BiFunction remappingFunction) {        Objects.requireNonNull(remappingFunction);        V oldValue;        if ((oldValue = get(key)) != null) {            V newValue = remappingFunction.apply(key, oldValue);            if (newValue != null) {                put(key, newValue);                return newValue;            } else {                remove(key);                return null;            }        } else {            return null;        }    }    default V compute(K key,            BiFunction remappingFunction) {        Objects.requireNonNull(remappingFunction);        V oldValue = get(key);        V newValue = remappingFunction.apply(key, oldValue);        if (newValue == null) {            // delete mapping            if (oldValue != null || containsKey(key)) {                // something to remove                remove(key);                return null;            } else {                // nothing to do. Leave things as they were.                return null;            }        } else {            // add or replace old mapping            put(key, newValue);            return newValue;        }    }    default V merge(K key, V value,            BiFunction remappingFunction) {        Objects.requireNonNull(remappingFunction);        Objects.requireNonNull(value);        V oldValue = get(key);        V newValue = (oldValue == null) ? value :                   remappingFunction.apply(oldValue, value);        if(newValue == null) {            remove(key);        } else {            put(key, newValue);        }        return newValue;    }}

List的实现类:

Bindings, ConcurrentMap<K,V>, ConcurrentNavigableMap<K,V>, LogicalMessageContext, MessageContext, NavigableMap<K,V>, SOAPMessageContext, SortedMap<K,V>, AbstractMap, Attributes, AuthProvider, ConcurrentHashMap, ConcurrentSkipListMap, EnumMap, HashMap, Hashtable, IdentityHashMap, LinkedHashMap, PrinterStateReasons, Properties, Provider, RenderingHints, SimpleBindings, TabularDataSupport, TreeMap, UIDefaults, WeakHashMap

Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。 

HashMap和Hashtable的区别

HashMap几乎可以等价于Hashtable,除了HashMap是非synchronized的,并可以接受null(HashMap可以接受为null的键值(key)和值(value),而Hashtable则不行)。
HashMap是非synchronized,而Hashtable是synchronized,这意味着Hashtable是线程安全的,多个线程可以共享一个Hashtable;而如果没有正确的同步的话,多个线程是不能共享HashMap的。Java 5提供了ConcurrentHashMap,它是HashTable的替代,比HashTable的扩展性更好。
另一个区别是HashMap的迭代器(Iterator)是fail-fast迭代器,而Hashtable的enumerator迭代器不是fail-fast的。所以当有其它线程改变了HashMap的结构(增加或者移除元素),将会抛出ConcurrentModificationException,但迭代器本身的remove()方法移除元素则不会抛出ConcurrentModificationException异常。但这并不是一个一定发生的行为,要看JVM。这条同样也是Enumeration和Iterator的区别。
由于Hashtable是线程安全的也是synchronized,所以在单线程环境下它比HashMap要慢。如果你不需要同步,只需要单一线程,那么使用HashMap性能要好过Hashtable。
HashMap不能保证随着时间的推移Map中的元素次序是不变的。

注意

sychronized意味着在一次仅有一个线程能够更改Hashtable。就是说任何线程要更新Hashtable时要首先获得同步锁,其它线程要等到同步锁被释放之后才能再次获得同步锁更新Hashtable。
Fail-safe和iterator迭代器相关。如果某个集合对象创建了Iterator或者ListIterator,然后其它的线程试图“结构上”更改集合对象,将会抛出ConcurrentModificationException异常。但其它线程可以通过set()方法更改集合对象是允许的,因为这并没有从“结构上”更改集合。但是假如已经从结构上进行了更改,再调用set()方法,将会抛出IllegalArgumentException异常。
结构上的更改指的是删除或者插入一个元素,这样会影响到map的结构。
HashMap可以通过下面的语句进行同步:
Map m = Collections.synchronizeMap(hashMap);

结论

Hashtable和HashMap有几个主要的不同:线程安全以及速度。仅在你需要完全的线程安全的时候使用Hashtable,而如果你使用Java 5或以上的话,请使用ConcurrentHashMap吧。