ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Map.Entry 接口

2019-09-10 17:06:11  阅读:307  来源: 互联网

标签:Map Comparator 抛出 接口 getKey Entry entry 异常


原文链接:https://www.cnblogs.com/young-youth/p/11497269.html

该接口,定义一个键值对实体接口。Map.entrySet 方法返回的 Set 集合中的实体就是实现这个 它。只有一种方法可以获得 Map.Entry 对象的引用,那就是通过集合的迭代器。并且 Map.entry 只在迭代期间有效,更加准确的是意思是,如果在获得迭代器以后,修改了集合,那么 Map.Entry 的行为是未定义的1。除非调用 Map.Entry 的 setValue 设置下修改的值。

API文档中的这段话,说的让我有点费解。修改集合以后,Map.Entry 的行为是未定义的,LZ 做了实验,发现并没有触发到什么非法,未定义的操作。

    Map<String, String> stringMap = new HashMap<>(16);

    stringMap.put("key1", "value1");
    stringMap.put("key2", "value2");
    stringMap.put("key3", "value3");
    stringMap.put("key4", "value4");
    stringMap.put("key5", "value5");
    stringMap.put("key6", "value6");

    Iterator<Map.Entry<String, String>> iterator = stringMap.entrySet().iterator();

    Map.Entry<String, String> next = iterator.next();
    stringMap.remove(next.getKey());
    stringMap.put(next.getKey(),"value7");

就如上面的代码所示,在得到 Entry 以后,对集合进行了修改,也没有触发什么非法的状态,抛出什么异常来。这里的未定义,其实是一个很无懈可击的答案,既然是未定义的,那么它们做出的任何行为,都是可以被理解的,所以它没抛出什么异常,那也是对的,抛出异常也是对的,你不应该单方面的任认为它应该怎样怎样,因为它是未定义,不同的实现有不同的反应。

而且这里的合法与非法,是针对 Entry 的值来说,在你获取以后,有人又修改了集合的内容,这时候你获取的 Entry 的内容,也会随之改变,但是你可能不知道集合被修改过,所以这里的合法与非法,是 Entry 是否可以再被信任的问题,所以想要修改值的时候,应该用 entry 的 setValue() 方法,显示的去改。

1|1K getKey()
返回实体对应的 key 。

可能抛出的异常 IllegalStateException ,这个异常可以 选择性 的实现。如果实现了,则异常的抛出条件:如果对应的 entry 已经被移除了,则抛出该异常。

比如,HashMap 的 Entry 就没有实现抛出该异常:

static class Node<K,V> implements Map.Entry<K,V> {
    ...
    public final K getKey()        { return key; }
    ...
}

而EnumMap 则实现了该异常,并且遵守了异常抛出条件:

private class Entry implements Map.Entry<K,V> {
       ...
        public K getKey() {
            checkIndexForEntryUse();
            return keyUniverse[index];
        }
        ...
        private void checkIndexForEntryUse() {
            if (index < 0)
                throw new IllegalStateException("Entry was removed");
        }
}

1|2V getValue()
返回 entry 实体对应的 value 。

如果集合中此 entry 的映射关系已经被移除,即使是通过 iterator 的 remove 方法,getValue() 方法的返回值也是 未定义。因此,不同的实现,对此方法有不同的做法,HashMap 对其没做什么,正常返回值,即使映射关系被删除了。EnumMap 则抛出异常。

可能抛出的异常 IllegalStateException ,这个异常可以 选择性 的实现。如果实现了,则异常的抛出条件:如果对应的 entry 已经被移除了,则抛出该异常。

1|3V setValue(V value)
替换当前 entry 的 value 为传进来的给定的 value ,(map 中对应的 value 也被改变)。如果集合中 entry 的映射关系已经被通过迭代器的 remove() 方法移除,则调用这个方法的行为是 未定义 的。看具体的实现如何操作。同样的 HashMap 对此行为,返回正确的值。EnumMap 则抛出异常。

返回设置值之前,当前 entry 对应的值。

可能抛出的异常:

UnsupportedOperationException :如果集合不支持 put 操作,则抛出此异常。
ClassCastException:如果传入的参数,不能转换存储到集合中,则抛出此异常,类型转换异常。
NullPointerException:如果集合不允许存入 null ,其传入的参数确实是 null ,则抛出此异常。
IllegalArgumentException:如果传入的值的某些属性,阻止其存入集合中,则抛出此异常。
IllegalStateException :此异常可选择是否实现。如果 entry 已经被移除了,则抛出此异常。
1|4boolean equals(Object o)
将传入的参数对象与当前的 entry 比较,如果传入的对象也是一个 entry 类型,并且它们具有相同的映射关系,则返回 true 。

更确切的说,相同的映射关系,应该写成下面的代码: key ,value 分别相等。

(e1.getKey()==null ? e2.getKey()==null : e1.getKey().equals(e2.getKey()))  
&&
(e1.getValue()==null ? e2.getValue()==null: e1.getValue().equals(e2.getValue()))

这样做以后,可以确保 equals 方法在不同的 Map.Entry 实现之前都能正确的工作。

1|5int hashCode()
返回当前 entry 的哈希码。entry 的哈希码计算方法如下:

(e.getKey()==null   ? 0 : e.getKey().hashCode())
^
(e.getValue()==null ? 0 : e.getValue().hashCode())

这样做,确保 e1.equals(e2) 时,e1.hashCode()==e2.hashCode() ,当前前提是,这个两个 entry 的 KV 的 hashCode 方法一致 。

下面几个方法是 1.8 添加进来的。属于静态方法

1|6comparingByKey()
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());
}
返回一个 Comparator ,该比较器对 entry 的 key进行 自然排序,即按照字典顺序,0-9,a-z 。

返回的比较器,实现了 serializable 接口。代码中 (Comparator<Map.Entry<K, V>> & Serializable) 是强转的含义。强转可以这样写,转为二者的结合,但是 & 后面必须是 接口 。

可能抛出的异常:NullPointerException ,如果比较的 entry 的 key 是 null,则抛出此异常。

1|7comparingByValue( )
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 ,该比较器对 entry 的 key进行 自然排序 。

返回的比较器,实现了 serializable 接口。

可能抛出的异常:NullPointerException ,如果比较的 entry 的 key 是 null,则抛出此异常。

1|8comparingByKey(Comparator cmp)
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());
}
返回一个比较器,该比较器对 entry 的 key 进行比较,根据传入的比较器。如果传入的比较器实现了 serializable 接口,那么返回的比较器也一并实现该接口。

1|9comparingByValue(Comparator cmp)
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());
}
返回一个比较器,该比较器对 entry 的 value 进行比较,根据传入的比较器。如果传入的比较器实现了 serializable 接口,那么返回的比较器也一并实现该接口。
深圳网站建设:https://www.sz886.com

标签:Map,Comparator,抛出,接口,getKey,Entry,entry,异常
来源: https://blog.csdn.net/chenmh12/article/details/100704432

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有