Map接口

此处讲的是JDK8的Map接口

  1. Map与Collection并列存在,用于保存具有映射关系的数据Key-Value
  2. Map中的Key和Value可以使任何引用类型的数据,会封装到HashMap<span data-formula="Node对象中
  3. Map中的key不允许重复,原因和HashSet一样。当有相同的key时,等价于替换,新的value将旧value替换
  4. Map中的value可以重复
  5. Map中的key可以为null, value也可以为null, 注意key为null,只能有一个, value为null可以有多个
  6. 常用String类作为Map的key
  7. key和value之间存在单向一对一关系,即通过指定的key总能找到对应的Key
  8. Map存放数据的key-value示意图,一对k-v是放在一个HashMap" aria-hidden="true">Node中的,又因为Node实现了Entry接口,有些书上也说一对k-v就是一个Entry alt text

Map体系继承图

alt text

Map接口常用方法

  1. put添加
  2. remove根据key删除
  3. get根据key获取
  4. size
  5. isEmpty
  6. clear
  7. containsKey

Map遍历方法

  1. containsKey:查找键是否存在
  2. keySet:获取所有的键
  3. entrySet:获取所有关系k-v
  4. values:获取所有的值 alt text

第一组方法:先取出所有的key,通过key取出对应的Value

Set keyset = map.keySet();
//(1)增强for
for(Object key:keyset){
    //输出map.get(key)
}
//(2)迭代器
Iterator iterator = keyset.iterator();
while(iterator.hasNext()){
    Object key = iterator.next();
    //输出map.get(key)
}

第二组方法:取出所有values

map.values()

第三组方法:通过EntrySet,获取k-v

Set entrySet = map.entrySet();
//(1)增强for
for(Object entry: entrySet){
    Map.Entry m = (Map.Entry)entry;
    //输出m.getKey()和m.getValue()
}
//(2)迭代器
Iterator iterator = entrySet.iterator();
while(iterator.hasNext()){
    Object entry = iterator.next();
    Map.Entry m = (Map.Entry)entry;
    //输出m.getKey()和m.getValue()
}

HashMap小结

  1. Map接口常用实现类:HashMap, Hashtable和Properties
  2. HashMap是Map接口使用频率最高的实现类。
  3. HashMap是以key-val对的方式来存储数据
  4. key不能重复,但value可以从夫,允许使用null键和null值
  5. 如果添加相同的key,会覆盖掉原来的key-val,即修改val,key不会替换
  6. 与HashSet一样,不保证映射顺序,因为底层是以hash表方式存储的
  7. HashMap没有实现同步,线程不安全

HashMap扩容机制,同HashSet

  1. HashMap底层维护了Node类型的数据table,默认为null
  2. 创建对象时,加载因子(loadfactor)初始化为0.75
  3. 当添加key-val时,通过key的哈希值得到在table的索引。然后判断该索引处是否有元素,如果没有元素直接添加。如果该索引处有元素,继续判断该元素的key是否和准备加入的key相等,如果相等,则直接替换val;如果不相等宣布要判断是树结构还是链表结构,做出对应处理。如添加时发现容量不够,则需要扩容
  4. 第一次添加,则需要扩容table容量为16,临界值(threshold)为12
  5. 以后再扩容,则需要扩容table容量为原来两倍,临界值为原来两倍
  6. java8中,如果一条链表元素超过TREEIFY_THRESHOLD(默认为8), 并且table的大小 >= MIN_TREEIFY_CAPACITY(默认64),就会进行树化(红黑树)

HashTable

  1. 存放的元素是键值对:k-v
  2. Hashtable的键和值都不能为null
  3. Hashtable使用方法基本和HashMap一样
  4. Hashtable是线程安全的,HashMap是线程不安全的

Hashtable底层

  1. 底层有数组Hashtable<span data-formula="Entry[], 初始化大小为11
  2. 临界值threshold 8=11*0.75
  3. 扩容方法: 当达到临界值,还在添加k-v到Entry中时,按照 int new Capacity = (oldCapacity<<1) +1 扩容,即扩容1倍+1

Hashtable VS HashMap

alt text

Properties

  1. Properties类继承自Hashtable类并实现了Map接口,也是使用键值对的形式来保存数据
  2. 使用特点与Hashtable类似
  3. Properties还可以用于从xxx.properties文件中,建在数据到Properties类对象,并进行读取和修改
  4. 工作后xxx.properties文件常作为配置文件" aria-hidden="true">Entry[], 初始化大小为11
  5. 临界值threshold 8=11*0.75
  6. 扩容方法: 当达到临界值,还在添加k-v到Entry中时,按照 int new Capacity = (oldCapacity<<1) +1 扩容,即扩容1倍+1

Hashtable VS HashMap

alt text

Properties

  1. Properties类继承自Hashtable类并实现了Map接口,也是使用键值对的形式来保存数据
  2. 使用特点与Hashtable类似
  3. Properties还可以用于从xxx.properties文件中,建在数据到Properties类对象,并进行读取和修改
  4. 工作后xxx.properties文件常作为配置文件

本文章使用limfx的vscode插件快速发布