标签:
@author ixenos
尽量返回接口而非实际的类型,如返回List、Set、Map而非ArrayList、HashSet、HashMap,便于更换数据结构,而客户端代码不用改变。这就是针对抽象编程
Map.entrySet 方法返回Map映射的 Set 视图Set<Map.Entry<K,V>>,维护entry键值对
该 set 受Map映射支持,所以对Map映射的更改可在此 set 中反映出来,反之亦然!
如果对该 set 进行迭代的同时修改了Map映射,外部modCount改变而内部的xxxmodCount还在自己的节奏(通过迭代器自己的 remove 操作,或者通过对迭代器返回的映射项执行 setValue 操作除外),则迭代结果是不确定的;简单来说就是iterator的对象不受Map支持,Map自行修改的时候不会通知到他,modCount异常,会发生如NullPointException之类的异常
该set 支持元素移除,通过 Iterator.remove、Set.remove、removeAll、retainAll 和 clear这几种操作操作可从映射中移除相应的映射关系,但它不支持 add 或 addAll 操作
public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) { Set<T> keys = new HashSet<T>(); for (Entry<T, E> entry : map.entrySet()) { //判断当前entry是否含有value if (Objects.equals(value, entry.getValue())) { //通过含有value的entry得到对应的key keys.add(entry.getKey()); } } return keys; }
public static <T, E> Set<T> getKeysByValue(Map<T, E> map, E value) { return map.entrySet() .stream() .filter(entry -> Objects.equals(entry.getValue(), value)) .map(Map.Entry::getKey) .collect(Collectors.toSet()); }
public static <T, E> T getKeyByValue(Map<T, E> map, E value) { for (Entry<T, E> entry : map.entrySet()) { if (Objects.equals(value, entry.getValue())) { //一找到就return return entry.getKey(); } } return null; }
还可以不用Java集合框架,用Google的开源框架Guava,其中的BiMap可以由value得key
BiMap<Token, Character> tokenToChar = ImmutableBiMap.of(Token.LEFT_BRACKET, ‘[‘, Token.LEFT_PARENTHESIS, ‘(‘); Token token = tokenToChar.inverse().get(‘(‘); Character c = tokenToChar.get(token);
找到key对应的entry,如果非空,则添加时(只是)覆盖value
//e是一个node<K,V>对象,也就是一个entry //value是put进来的 if (e != null) { // existing mapping for key V oldValue = e.value; if (!onlyIfAbsent || oldValue == null) //从这里可以看出是找到对应entry然后改变值 e.value = value; afterNodeAccess(e); return oldValue; }
public synchronized V put(K key, V value) { // Make sure the value is not null if (value == null) { throw new NullPointerException(); } // Makes sure the key is not already in the hashtable. Entry<?,?> tab[] = table; int hash = key.hashCode(); int index = (hash & 0x7FFFFFFF) % tab.length; @SuppressWarnings("unchecked") Entry<K,V> entry = (Entry<K,V>)tab[index]; for(; entry != null ; entry = entry.next) { //先判断哈希是因为比equals快,而且用的逻辑与 if ((entry.hash == hash) && entry.key.equals(key)) { V old = entry.value; //可以看出还是替换掉了旧有的值 entry.value = value; return old; } } addEntry(hash, key, value, index); return null; }
/** * Returns <tt>true</tt> if this map maps one or more keys to the specified value. * 即“如果这个映射表有一个或多个key映射到一个值上时,返回true” * @param value value whose presence in this map is to be tested * @return <tt>true</tt> if this map maps one or more keys to the * specified value */ public boolean containsValue(Object value) { Node<K,V>[] tab; V v; if ((tab = table) != null && size > 0) { //遍历每一个桶bucket(同样hash值的entry(Node)在一个桶中),一个桶存放一个双链表 for (int i = 0; i < tab.length; ++i) { //遍历桶中的链表,把所有映射value的key揪出来 for (Node<K,V> e = tab[i]; e != null; e = e.next) { //后继结点e.next指向的是另一个同hash的entry的前驱结点key(Node是双链表结点) if ((v = e.value) == value || (value != null && value.equals(v))) return true; } } } return false; }
标签:
原文地址:http://www.cnblogs.com/ixenos/p/5661837.html