我习惯了无所谓,却不是真的什么都不在乎。 请关注:源码猎人 目录 Map是我们常用集合之一,它用于保存具有映射关系的数据。Map集合中的每一个元素都是由键值对构成。Map中所有的键不能重复,但是值可以重复。 Map 一个高度封装的集合接口,它派生出来的类或接口如下 整个Map框架中用到了Dictionary 抽象类,其他类都是Map直接或间接派生出来。 Map 接口定义了集合的基本行为,及内部元素模型。 Map 未实现方法 Map 默认方法 根据key获取值,为空或不存在返回默认值 如果key不存在或为空就添加此键值对 如果key对应的值与value一样就删除 使用新值替换旧值,旧值与key对应值不同时返回false 当key存在时,用value覆盖原值,不存在时返回空 方法定义 定义了基本键值对行为 定了所有Map集合的基本骨架 AbstractMap属性 AbstractMap构造函数 AbstractMap未实现的方法 AbstractMap实现了Map接口中除entrySet()以外的方法。AbstractMap已实现的方法 equals判断方式,先判断类型,在判断长度,之后判断元素,这跟List不同是,List中元素顺序不同会导致equals不同,这儿用的是包含和取值方式比较。第一个元素要么都是空,其他元素可以无顺序限制。 hashcode方法是所有元素hashcode求和 Dictionary类,顾名思义,就是字典类,算是早期的Map,不过该类基本上已经废弃了。为什么废弃呢,大致看下Dictionary的源码就知道了。除了常规的get,put请求外,还提供了一些遍历的方法,返回的是Enumeration类型。而Enumeration接口其实算是被Iterator替换了,因为Iterator提供的功能更多,更方便。 构造函数 的方法 方法 方法 SortedMap提供了获取最大值与最小值的方法,但对于一个已经排序的数据集,除了最大值与最小值之外,我们还想对任何一个元素,找到比它小的值和比它大的值,还可以按照原有的顺序倒序排序等,这时候就可以用NavigableMap接口 1、你都知道哪些常用的Map集合? 2、Collection 集合接口和Map接口有什么关系? 3、AbstractMap 作用是什么? AbstractMap 提供了 Map 的基本实现,使得我们以后要实现一个 Map 不用从头开始,只需要继承 AbstractMap, 然后按需求实现/重写对应方法即可。 4、Map 的键可以重复吗?为什么? Map 的键不能重复,因为所有Map中,都是通过键来计算元素在集合中的位置,如果键重复,就没办法定位元素,那么所有Map算法都需要修改。 5、Map 的值可以重复吗?为什么? Map 的值可以重复,应为在计算元素位置时,值不参与运算,所以值重不重复都没关系。
简介
Map 框架
Map 接口源码解读
public interface Map<K,V>
// 获取元素个数 int size(); // 是否为空 boolean isEmpty(); // 是否包含key boolean containsKey(Object key); // 是否包含value boolean containsValue(Object value); // 根据key取值 V get(Object key); // 添加元素 V put(K key, V value); // 移除key V remove(Object key); // 添加一个Map集合 void putAll(Map<? extends K, ? extends V> m); // 清除 void clear(); // 获取整个key集合 Set<K> keySet(); // 获取所有值 Collection<V> values(); // 获取所有键值对 Set<Map.Entry<K, V>> entrySet(); // 比较是否一样 boolean equals(Object o); // 获取集合hashCode int hashCode();
default V getOrDefault(Object key, V defaultValue) { V v; // key不存在或key对应值为空返回默认值,否有返回实际值 return (((v = get(key)) != null) || containsKey(key)) ? v : defaultValue; }
default V putIfAbsent(K key, V value) { V v = get(key); // key为空则添加 if (v == null) { v = put(key, value); } return v; }
default boolean remove(Object key, Object value) { Object curValue = get(key); // value不一样或key不存在返回false 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); // 旧值与key对应值不同时返回false 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; }
Map 内部类Entry接口源码
interface Entry<K,V>
K getKey(); V getValue(); V setValue(V value); boolean equals(Object o); int hashCode();
AbstractMap 抽象类源码解读
public abstract class AbstractMap<K,V> implements Map<K,V>
// 键集合 transient Set<K> keySet; // 值集合 transient Collection<V> values;
protected AbstractMap() { }
public abstract Set<Entry<K,V>> entrySet();
在这些已实现的方法中,只需要关注equals和hashcode方法即可,其他方法子类均已覆盖
public boolean equals(Object o) { // 地址一样时为true if (o == this) return true; // 不是Map或子类实例时为false if (!(o instanceof Map)) return false; // 强转o为Map Map<?,?> m = (Map<?,?>) o; // m长度为空 if (m.size() != size()) return false; try { // 遍历当前集合所有元素 Iterator<Entry<K,V>> i = entrySet().iterator(); while (i.hasNext()) { Entry<K,V> e = i.next(); K key = e.getKey(); V value = e.getValue(); // 有任意一个值不像等就返回false if (value == null) { if (!(m.get(key)==null && m.containsKey(key))) return false; } else { if (!value.equals(m.get(key))) return false; } } } catch (ClassCastException unused) { return false; } catch (NullPointerException unused) { return false; } // 循环完返回true return true; }
public int hashCode() { int h = 0; // 遍历所有元素 Iterator<Entry<K,V>> i = entrySet().iterator(); while (i.hasNext()) // 元素hashCode累加 h += i.next().hashCode(); return h; }
Dictionary 抽象类源码解读
public abstract class Dictionary<K,V>
public Dictionary() { }
abstract public int size(); abstract public boolean isEmpty(); abstract public Enumeration<K> keys(); abstract public Enumeration<V> elements(); abstract public V get(Object key); abstract public V put(K key, V value); abstract public V remove(Object key);
NavigableMap 接口源码解读
public interface NavigableMap<K,V> extends SortedMap<K,V>
// 找到第一个比指定的key小的值 Map.Entry<K,V> lowerEntry(K key); // 找到第一个比指定的key小的key K lowerKey(K key); // 找到第一个小于或等于指定key的值 Map.Entry<K,V> floorEntry(K key); // 找到第一个小于或等于指定key的key K floorKey(K key); // 找到第一个大于或等于指定key的值 Map.Entry<K,V> ceilingEntry(K key); //找到第一个大于或等于指定key的key K ceilingKey(K key); // 找到第一个大于指定key的值 Map.Entry<K,V> higherEntry(K key); //找到第一个大于指定key的key K higherKey(K key); // 获取最小值 Map.Entry<K,V> firstEntry(); // 获取最大值 Map.Entry<K,V> lastEntry(); // 删除最小的元素 Map.Entry<K,V> pollFirstEntry(); // 删除最大的元素 Map.Entry<K,V> pollLastEntry(); //返回一个倒序的Map NavigableMap<K,V> descendingMap(); // 返回一个Navigable的key的集合,NavigableSet和NavigableMap类似 NavigableSet<K> navigableKeySet(); // 对上述集合倒序 NavigableSet<K> descendingKeySet();
SortedMap 接口源码解读
public interface SortedMap<K,V> extends Map<K,V>
// 排序比较器 Comparator<? super K> comparator(); // 获取其中一段 SortedMap<K,V> subMap(K fromKey, K toKey); // 获取小于toKey的键值对 SortedMap<K,V> headMap(K toKey); /// 获取大于fromKey的键值对 SortedMap<K,V> tailMap(K fromKey); // 返回此映射中当前第一个键 K firstKey(); // 返回映射中当前最后一个键 K lastKey(); // 与父接口Map中的定义一样,但有顺序 Set<K> keySet(); // 与父接口Map中的定义一样,但有顺序(根据key的顺序) Collection<V> values(); // 与父接口Map中的定义一样,但有顺序(根据key的顺序) Set<Map.Entry<K, V>> entrySet();
常见面试题
HashMap、HashTable、LinkedHashMap、ConcurrentHashMap。
没关系,Collection是List、Set父接口不是Map父接口。
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算