Map集合

说明

在这里插入图片描述

将键映射到值的对象。Map不能包含重复的键;每个键最多可以映射到一个值。

这个接口取代了 Dictionary 类,后者是一个完全抽象的类而不是一个接口。

Map 接口提供三个集合视图,允许将Map的内容视为一组键、一组值或一组键值映射。地图的 order 被定义为Map集合视图上的迭代器返回其元素的顺序。一些Map实现,比如 TreeMap 类,对它们的顺序做出了具体的保证;其他的,比如 HashMap 类没有。

注意:如果将可变对象用作映射键,则必须非常小心。如果对象的值以影响 equals 比较的方式更改,而对象是映射中的键,则不会指定映射的行为。此禁令的一个特殊情况是不允许映射将自身包含为键。虽然允许Map将自身包含为值,但建议格外小心:equals 和 hashCode 方法不再在此类Map上明确定义。

所有通用Map实现类都应该提供两个“标准”构造函数:一个创建空映射的 void(无参数)构造函数,以及一个带有 Map 类型的单个参数的构造函数,它创建具有与其参数相同的键值映射的新映射。实际上,后一个构造函数允许用户复制任何映射,生成所需类的等效映射。没有办法强制执行此建议(因为接口不能包含构造函数),但 JDK 中的所有通用映射实现都符合。

此接口中包含的“破坏性”方法,即修改它们操作的Map的方法,如果此地图不支持该操作,则指定抛出UnsupportedOperationException。在这种情况下,如果调用对Map没有影响,则这些方法可能(但不是必需)抛出 UnsupportedOperationException。例如,如果要“叠加”映射的映射为空,则在不可修改的映射上调用 putAll(Map) 方法可能(但不是必须)抛出异常。

某些地图实现对它们可能包含的键和值有限制。例如,有些实现禁止空键和值,有些实现对其键的类型有限制。尝试插入不合格的键或值会引发未经检查的异常,通常是 NullPointerException 或 ClassCastException。尝试查询不合格的键或值的存在可能会引发异常,或者它可能只是返回 false;一些实现会表现出前一种行为,而另一些会表现出后者。更一般地,尝试对不合格的键或值执行操作,其完成不会导致不合格的元素插入到映射中,可能会引发异常,也可能会成功,具体取决于实现的选择。在此接口的规范中,此类异常被标记为“可选”。

Collections Framework 接口中的许多方法都是根据Objectequals(Object) equals 方法定义的。例如, containsKey(Object) containsKey(Object key)} 方法的规范说:“当且仅当此映射包含键 k 的映射时,才返回 true 使得 (key==null ? k==null : key.equals(k))。”本规范应not 被解释为暗示使用非空参数 key 调用 Map.containsKey 将导致 key.equals(k) 为任何键 k 调用。实现可以自由地实现优化,从而避免 equals 调用,例如,通过首先比较两个键的哈希码。 ( ObjecthashCode() 规范保证哈希码不相等的两个对象不能相等。)更一般地说,各种集合框架接口的实现可以自由地利用底层 Object 方法的指定行为实施者认为合适的任何地方。

某些执行映射递归遍历的映射操作可能会失败,但映射直接或间接包含自身的自引用实例除外。这包括 clone()、 equals()、 hashCode() 和 toString()方法。实现可以选择性地处理自引用场景,但是大多数当前的实现都没有这样做。

源码分析(部分)

 int size(); //map中键值对的数量

    /**
     * 返回true表示map中没有键值对
     */
    boolean isEmpty();

    /**
     * map中是否存在传入的键值
     */
    boolean containsKey(Object key);

    /**
     *map中是否存在传入的value
     */
    boolean containsValue(Object value);

    /**
     *获得相应键值映射的值value
     */
    V get(Object key);
/*
   存放键值映射
     */
    V put(K key, V value);

    /**
     *移除相应1键值对应的值,并且返回
     */
    V remove(Object key);


   

    /**
     * 将传入的Map m 中的键值映射放进当前Map中。
     */
    void putAll(Map<? extends K, ? extends V> m);

    /**
     *清空当前Map中的键值对
     */
    void clear();


  

    /**
     此映射中包含的键的集合视图
     */
    Set<K> keySet();

    /**
     返回一个集合视图,包含该map中所有的value
     */
    Collection<V> values();

    /**
     * 此映射中包含的映射的集合视图
     */
    Set<Map.Entry<K, V>> entrySet();
    interface Entry<K,V> {
        /**
         * 返回与此条目对应的键。
         */
        K getKey();

        /**
         * 返回与此条目对应的值。
         */
        V getValue();

        /**
         * 用指定的值替换与此条目对应的值(可选操作)。
         */
        V setValue(V value);

        /**
         * 比较指定的对象与此项是否相等。
         */
        boolean equals(Object o);

        /**
         * 此map条目的hash值
         */
        int hashCode();

        /**
         * 返回一个比较器,它在键上按自然顺序比较
         */
        public static <K extends Comparable<? super K>, V> Comparator<Map.Entry<K,V>> comparingByKey() {
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> c1.getKey().compareTo(c2.getKey());
        }

        /**
         *返回一个比较器,它按值的自然顺序比较
         */
        public static <K, V extends Comparable<? super V>> Comparator<Map.Entry<K,V>> comparingByValue() {
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> c1.getValue().compareTo(c2.getValue());
        }

        /**
         *返回一个比较器,它使用给定的键来比较
         */
        public static <K, V> Comparator<Map.Entry<K, V>> comparingByKey(Comparator<? super K> cmp) {
            Objects.requireNonNull(cmp);
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> cmp.compare(c1.getKey(), c2.getKey());
        }

        /**
         * 返回一个比较器,它使用给定的值来比较
         */
        public static <K, V> Comparator<Map.Entry<K, V>> comparingByValue(Comparator<? super V> cmp) {
            Objects.requireNonNull(cmp);
            return (Comparator<Map.Entry<K, V>> & Serializable)
                (c1, c2) -> cmp.compare(c1.getValue(), c2.getValue());
        }
    }


总结

1、Map的三大特点:
a.包含键值对
b.键唯一
c.键对应的值唯一
2. Map的分类
1)EnumMap
a、EnumMap是一个与枚举类一起使用的Map实现,EnumMap中所有key都必须是单个枚举类的枚举值。创建EnumMap时必须显式或隐式指定它对应的枚举类
b、EnumMap在内部以数组形式保存,所以这种实现形式非常紧凑、高效
c、EnumMap根据key的自然顺序(即枚举值在枚举类中的定义顺序)来维护来维护key-value对的次序。当程序通过keySet()、entrySet()、values()等方法来遍历EnumMap时即可看到这种顺序
d、EnumMap不允许使用null作为key值,但允许使用null作为value。如果试图使用null作为key将抛出NullPointerException异常。如果仅仅只是查询是否包含值为null的key、或者仅仅只是使用删除值为null的key,都不会抛出异常。
2)WeakHashMap
在这里插入图片描述

WeakHashMap继承于AbstractMap,并且实现了Map接口。WeakHashMap是哈希表,但是它的键是"弱键"。WeakHashMap中保护几个重要的成员变量:table, size, threshold, loadFactor, modCount, queue。

3)HashMap
HashMap是基于哈希表的Map接口的非同步实现。此实现提供所有可选的映射操作,并允许使用null值和null键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变,HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体
4)IdentityHashMap
区别与其他的键不能重复的容器,IdentityHashMap允许key值重复,但是——key必须是两个不同的对象,即对于k1和k2,当k1==k2时,IdentityHashMap认为两个key相等,而HashMap只有在k1.equals(k2) == true 时才会认为两个key相等。 IdentityHashMap的数据很简单,底层实际就是一个Object数组,在逻辑上需要看成是一个环形的数组,解决冲突的办法是:根据计算得到散列位置,如果发现该位置上已经有元素,则往后查找,直到找到空位置,进行存放,如果没有,直接进行存放。当元素个数达到一定阈值时,Object数组会自动进行扩容处理。
5)Dictionary
Dictionary 类是一个抽象类,用来存储键/值对,作用和Map类相似。给出键和值,你就可以将值存储在Dictionary对象中。一旦该值被存储,就可以通过它的键来获取它。所以和Map一样, 属于一个泛型集合:DIctionary
6)HashTable
Hashtable继承自Dictionary类,Hashtable 中的方法是Synchronize(同步锁)的,一般在多线程并发的环境下使用。
7)SortedMap
它是map接口下派生的一个子接口,SortedMap的实现类为TreeMap;
8)NavigableMap
扩展的 SortedMap,具有了针对给定搜索目标返回最接近匹配项的导航方法。方法 lowerEntry、floorEntry、ceilingEntry 和 higherEntry 分别返回与小于、小于等于、大于等于、大于给定键的键关联的 Map.Entry 对象,如果不存在这样的键,则返回 null。类似地,方法 lowerKey、floorKey、ceilingKey 和 higherKey 只返回关联的键。所有这些方法是为查找条目而不是遍历条目而设计的。
9)TreeMap
特点
a.无序,不允许重复(无序指元素顺序与添加顺序不一致)
b.TreeMap集合默认会对键进行排序,所以键必须实现自然排序和定制排序中的一种
c…底层使用的数据结构是二叉树
排序:
a.TreeSet集合排序方式一:自然排序Comparable

http://blog.csdn.net/baidu_37107022/article/details/70207564
b.TreeSet集合排序方式二:定制排序Comparator
http://blog.csdn.net/baidu_37107022/article/details/70207633
10)LinkedHashMap
HashMap和双向链表合二为一即是LinkedHashMap。所谓LinkedHashMap,其落脚点在HashMap,因此更准确地说,它是一个将所Entry节点链入一个双向链表的HashMap。由于LinkedHashMap是HashMap的子类,所以LinkedHashMap自然会拥有HashMap的所有特性。比如,LinkedHashMap的元素存取过程基本与HashMap基本类似,只是在细节实现上稍有不同。当然,这是由LinkedHashMap本身的特性所决定的,因为它额外维护了一个双向链表用于保持迭代顺序。此外,LinkedHashMap可以很好的支持LRU算法;LinkedHashMap读取的时候输入顺序和插入数据时的顺序相同
3. map的遍历
Map集合是键值对形式存储值的,所以它的遍历也就是获取键和值,map的遍历有四种:
a.通过map.keySet()获取值

 Map<Integer, String> map = new HashMap<Integer, String>();
 
for (Integer in : map.keySet()) {
            //map.keySet()返回的是所有key的值
            String str = map.get(in);//得到每个key多对用value的值
             System.out.println(in + "     " + str);
        }

b.通过Map.entrySet使用iterator遍历key和value

Iterator<Map.Entry<Integer, String>> it = map.entrySet().iterator();
     while (it.hasNext()) {
          Map.Entry<Integer, String> entry = it.next();
           System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
      }

c.用for循环通过 Map.entrySet使用iterator遍历key和value(推荐,尤其是容量大的时候)

for (Map.Entry<Integer, String> entry : map.entrySet()) {
         //Map.entry<Integer,String> 映射项(键-值对)  有几个方法:用上面的名字entry
         //entry.getKey() ;entry.getValue(); entry.setValue();
         //map.entrySet()  返回此映射中包含的映射关系的 Set视图。
          System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
      }

d. 通过Map.values()遍历所有的value,但不能遍历key

for (String v : map.values()) {
           System.out.println("value= " + v);
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值