Java集合学习(映射Map)

初步了解了Collection当然也要了解一下Map,对此我对Map也进行简单的总结,算是学习的一个经历。

Map中常见的接口及实现类:

接口SortedMap
抽象类AbstractMap
实现类HashMap,TreeMap,HashTable,LinkedHashMap
Map:Map官方释义:将键映射到值的对象。一个映射不能包含重复的键(Key);每个键最多只能映射到一个值(Value)。白话文就是,Map就是用唯一标志来获取对应信息的容器。唯一标志就是Key,对应信息就是Value,Key不可重复,Value可以重复。(也可以理解为Key是同一个文件目录下的子目录,Value就是子目录里面的文件或其孙子目录)

SortedMap:是map接口一个子接口,SortedMap的实现类为TreeMap;该映射是根据其键的自然顺序进行排序的,或者根据通常在创建有序映射时提供的 Comparator 进行排序。

AbstractMap:此类提供 Map 接口的骨干实现,以最大限度地减少实现此接口所需的工作。常用的类HashMap和TreeMap都继承于它。

HashMap:基于哈希表的 Map 接口的非同步的实现。允许使用 null 值和 null 键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。是HashSet的底层实现,Key是无序的,数据结构是散列表结构,即数组+链表结构。JDK8以后的版本,当链表长度大于等于8链表结构变化为红黑树结构。

TreeMap:基于红黑树(Red-Black tree)的 NavigableMap(SortedMap是他的父接口) 实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。

HashTable:此类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null 对象都可以用作键或值。功能与HashMap几乎相同,但是它不允许记录的键或者值为空,它支持多线程并发,大部分方法都是Synchronize的,因此也导致了 Hashtable在写入时会比较慢,效率较低。

LinkedHashMap:它是Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。

基于以上描述。我初步涉猎了Map实现类的源码

1.HashMap

继承AbstractMap 实现Map,Cloneable, Serializable接口。
部分成员变量:

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;  //默认初始容量-必须是2的幂。默认为16
static final int MAXIMUM_CAPACITY = 1 << 30;  //最大容量 2的30次方 
static final float DEFAULT_LOAD_FACTOR = 0.75f;  //默认的加载因子
static final int TREEIFY_THRESHOLD = 8; // 转换红黑树的默认阈值 当链表长度到8时 转为红黑树。
transient Node<K,V>[] table; //哈希数组(哈希桶),存放链表。 长度是2的N次方,或者初始化时为0.
transient Set<Map.Entry<K,V>> entrySet;   保存缓存entrySet()
final float loadFactor; //哈希表的加载因子。,用于计算哈希表元素数量的阈值。 
int threshold;//要调整大小的下一个大小值(容量*负载系数)。哈希表内元素数量的阈值,当哈希表内元素数量超过阈值时,会发生扩容resize()。

构造方法:

HashMap() //构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。 
HashMap(int initialCapacity) //构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。 
HashMap(int initialCapacity, float loadFactor) // 构造一个带指定初始容量和加载因子的空 HashMap。 initialCapacity值为初始最大容量(不大于2的30次方,如果超过,则默认为2的30次方),loadFactor 加载因子,默认0.75 不能赋值负数 
HashMap(Map<? extends K,? extends V> m) // 构造一个映射关系与指定 Map 相同的新 HashMap。 

常用方法:

 void clear() //从此映射中移除所有映射关系。 
 Object clone() //返回此 HashMap 实例的浅表副本,并不复制键和值本身。 
 V get(Object key) //返回指定键所映射的值;如果对于该键来说,此映射不包含任何映射关系,则返回 null。 
 boolean isEmpty() // 如果此映射不包含键-值映射关系,则返回 true。 
 V put(K key, V value) //在此映射中关联指定值与指定键。 
 V remove(Object key) //从此映射中移除指定键的映射关系(如果存在)。 
 int size() //返回此映射中的键-值映射关系数。 

2.TreeMap

继承AbstractMap 实现NavigableMap<K,V>, Cloneable, Serializable接口。
部分成员变量:

private final Comparator<? super K> comparator; //比较器用于维护树映射中的顺序,如果使用键的自然顺序,则为null。
private transient Entry<K,V> root; //根节点
private transient int size = 0; // 树中的条目数(节点数)
private transient int modCount = 0; // 对树进行结构性修改的次数

构造方法:

TreeMap() // 使用键的自然顺序构造一个新的、空的树映射。 
TreeMap(Comparator<? super K> comparator) // 构造一个新的、空的树映射,该映射根据给定比较器进行排序。 
TreeMap(Map<? extends K,? extends V> m) //构造一个与给定映射具有相同映射关系的新的树映射,该映射根据其键的自然顺序 进行排序。 
TreeMap(SortedMap<K,? extends V> m) // 构造一个与指定有序映射具有相同映射关系和相同排序顺序的新的树映射。 

常用方法:

  void clear() //从此映射中移除所有映射关系。 
 Object clone() //返回此 TreeMap 实例的浅表副本,并不复制键和值本身。
 V get(Object key) //返回指定键所映射的值,如果对于该键而言,此映射不包含任何映射关系,则返回 null。 
Set<Map.Entry<K,V>> entrySet() //返回此映射中包含的映射关系的 Set 视图。 
 V put(K key, V value) //将指定值与此映射中的指定键进行关联。 
 V remove(Object key) // 如果此 TreeMap 中存在该键的映射关系,则将其删除。 
 int size() // 返回此映射中的键-值映射关系数。

3.HashTable

继承 Dictionary<K,V> 实现Map,Cloneable, Serializable接口。
部分成员变量:

private transient Entry[] table; // 哈希数组。 Hashtable同样采用单链表存放解决冲突,每一个Entry本质上是一个单向链表。(哈希桶)  
 private transient int count;  // Hashtable中键值对的数量  
 private int threshold;  // 阈值,用于判断是否需要调整Hashtable的容量(threshold = 容量*加载因子)       
 private float loadFactor;  // 加载因子   
private transient int modCount = 0; // Hashtable被改变的次数,用于fail-fast机制的实现  

构造方法:

Hashtable() //用默认的初始容量 (11) 和加载因子 (0.75) 构造一个新的空哈希表。 
Hashtable(int initialCapacity) //用指定初始容量和默认的加载因子 (0.75) 构造一个新的空哈希表。 
Hashtable(int initialCapacity, float loadFactor) //用指定初始容量和指定加载因子构造一个新的空哈希表。 
Hashtable(Map<? extends K,? extends V> t) //构造一个与给定的 Map 具有相同映射关系的新哈希表。 

常用方法:

void clear() //将此哈希表清空,使其不包含任何键。
 Object clone() //创建此哈希表的浅表副本,并不复制键和值本身。 
 V get(Object key) //返回指定键所映射到的值,如果此映射不包含此键的映射,则返回 null. 更确切地讲,如果此映射包含满足 (key.equals(k)) 的从键 k 到值 v 的映射,则此方法返回 v;否则,返回 null。 
 boolean isEmpty() // 如果此映射不包含键-值映射关系,则返回 true。 
 V put(K key, V value) //将指定 key 映射到此哈希表中的指定 value。 
 V remove(Object key) //从哈希表中移除该键及其相应的值(如果存在)。 
 int size() //返回此哈希表中的键的数量。 

在这里我们了解一下HashTable 和HashMap的区别.
1.首先是HashTable 是线程安全的,支持并发,业务方法都是Synchronize的。而HashMap是非线程安全的,并发扩容时可能会出现死循环,所以一般并发时都会调用synchronizedMap(map)方法。

2.HashTable的版本是老版本(JDK1.0),HashMap是新版本(JDK1.2)。所以他们继承的类也不同,前者继承Dictionary(JDK1.0),后者继承AbstractMap(JDK1.2)。

3.效率不同 。HashTable 因为synchronized的方法,会进行阻塞效率会比HashMap要低很多。

4.默认初始容量不同 HashTable 默认初始容量是11 ,HashMap 默认初始容量是16。扩容不同,Hashtable不要求底层数组的容量一定要为2的整数次幂,而是乘2加1,而HashMap则因为调用tableSizeFor(int cap)方法,结果一定为2的整数次幂(例如果设置HashMap的初始容量是20,他第一次扩容容量会变成32 ,再次扩容为64,以此类推)。

5.HashTable 的Key和Value都不能为null,HashMap的Key可以为null,这样的Key只有一个;可以有一个或多个键所对应的值为null。

4.LinkedHashMap

继承HashMap实现Map接口。
部分成员变量:

transient LinkedHashMap.Entry<K,V> head;双链表的头部
transient LinkedHashMap.Entry<K,V> tail;双链表的尾部
private final boolean accessOrder;//双向链表中元素排序规则的标志位

构造方法:

LinkedHashMap() //构造一个带默认初始容量 (16) 和加载因子 (0.75) 的空插入顺序 LinkedHashMap 实例。 
LinkedHashMap(int initialCapacity) //构造一个带指定初始容量和默认加载因子 (0.75) 的空插入顺序 LinkedHashMap 实例。 
LinkedHashMap(int initialCapacity, float loadFactor) //构造一个带指定初始容量和加载因子的空插入顺序 LinkedHashMap 实例。 
LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) //构造一个带指定初始容量、加载因子和排序模式的空 LinkedHashMap 实例。 
LinkedHashMap(Map<? extends K,? extends V> m) //构造一个映射关系与指定映射相同的插入顺序 LinkedHashMap 实例。 

常用方法:
因为继承了HashMap,可以应用HashMap的常用方法。部分方法进行重写。
void clear() //从该映射中移除所有映射关系。 同时删掉双向链表的头尾两个元素。

 boolean containsValue(Object value) // 如果此映射将一个或多个键映射到指定值,则返回 true。因为双向链表关系遍历方式不同,更高效。
 V get(Object key) //返回此映射到指定键的值。 当Key为存在时,调用afterNodeAccess(e)方法。利用双向链表进行查询。

总体来说LinkedHashMap就是重写了几个方法,以满足其输出序列有序的需求,本质上就是一个HashMap,散列双向链表结构。

本文参考文章

面试必备:HashMap源码解析(JDK8) 张旭童.
倪升武的博客关于Map集合相关资料 eson_15 .
【Java】HashMap 和 HashTable 的区别到底是什么? Mlib.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值