Map.Entry接口源码阅读

Map接口是很多常用的像HashMap,HashTable,ConCurrentHashMap类的顶层接口;
这些常用的Map容器都实现了Map这个接口;

但是今天我要来讲的是Map接口中的一个内部接口Entry

public interface Map<K,V> {
 /**
     * A map entry (key-value pair).  The <tt>Map.entrySet</tt> method returns
     * a collection-view of the map, whose elements are of this class.  The
     * <i>only</i> way to obtain a reference to a map entry is from the
     * iterator of this collection-view.  These <tt>Map.Entry</tt> objects are
     * valid <i>only</i> for the duration of the iteration; more formally,
     * the behavior of a map entry is undefined if the backing map has been
     * modified after the entry was returned by the iterator, except through
     * the <tt>setValue</tt> operation on the map entry.
     *
     * @see Map#entrySet()
     * @since 1.2
     */
interface Entry<K,V> {
}
}

在描述当中可以看到,一个Map的键值对只能通过Map的entrySet()获得这个Map的键值对的集合后通过迭代器遍历获得其中的一对键值对;
并且只在遍历的过程中有效,除了在便利的时候通过Entry的setValue()修改之外,其余在这期间对Map的修改都会导致并发异常;

接下来看一下这个内部接口的一些常规抽象方法;
由于Entry(描述Map中的每一对键值对)只能通过Map.EntrySet()获得并遍历获得的;
所以其实它以下的一些方法都是需要配合迭代器来完成;

 注意:它具体实现还是会根据字类实现重写进行修改,我下面的文字描述都是根据源码给的英文描述进行翻译
 
        //function:返回遍历到的Map.Entry<K,V>的K;
        //@Throws IllegalStateException 子类实现后可能会发生的异常
        K getKey();

        //funcation:返回遍历到的Map.Entry<K,V>的V;
        //@Throws IllegalStateException 子类实现后可能会发生的异常
        V getValue();

        //funcation:将当前遍历到的Map.Entry<K,V>的V设置为value;
        V setValue(V value);

       //funcation:比较两个Map.Entry<K,V>是否equals
       //(e1.getKey()==null ?
       //e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &amp;&amp;
       //(e1.getValue()==null ?
       //e2.getValue()==null : e1.getValue().equals(e2.getValue()))
       //即比较两个Entry的Key和Value是否都相等;
        boolean equals(Object o);

       //function:返回遍历到的Map.Entry<K,V>的哈希值
       //(e.getKey()==null   ? 0 : e.getKey().hashCode()) ^
       //(e.getValue()==null ? 0 : e.getValue().hashCode())
       //实现类通过上述方法重写,这样可以避免相同的key,value的Entry却是不同的哈希值
        int hashCode();

总结一下:在利用迭代器进行遍历的时候getKey,getValue或者setValue
如果同时这个Map中的Entry被移除或者增加;会产生并发异常,除非是通过迭代器的remove方法
另外经测试如果修改了原本已经有的K,V不会报异常但是对象获得的值会同步被修改

接下来可以看到Java8的一些新特性的方法;
Java8除了增加default的默认方法之外,还增加了静态方法,
可以通过接口名.方法名来调用;
比如Map.Entry.方法名来调用;
//返回一个Comparator<Map.Entry<K,V>> 是用来比较Entry的Key1.compareTo(Key2);
//这个Comparator是Serializable的;这里用到了&强转 Java8新语法
//所以这里有个要求就是key实现了Comparable;	
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());
        }

//与上一个方法类似,只不过比较的是Entry中的value的值;        
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());
        }

 //用自定义的Comparator方法来创建一个比较Map.Entry<K,V>中的Key的Comparator对象
 //要求这个自定义的Comparator对象里比较的参数的类型是Map.Entry<K,V>中K的相同类型或者父类        
        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());
        }

//用自定义的Comparator方法来创建一个比较Map.Entry<K,V>的Value的Comparator对象
//要求这个自定义的Comparator对象的比较类型是Map.Entry<K,V>中跟V相同类型或者是他的父类        
        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());
        }

他们都是用来比较Map.Entry<K,V>中不同Entry的键或者值;如果是默认的比较的话;
要求比较的类型要实现Comparable接口因为会调用其中的compareTo方法;
(如果是比较Map.Entry<K,V>中自定义的类型,这个类型中需要有一个compareTo方法)
另外可以通过自定义的Comparator对象来构建比较的方式;
上述的Comparator对象都有一个特点是他们都可以实现序列化;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值