java基础笔记10-Map


map目录

Map接口实现类特点(很实用)

  1. 和Collection并列存在,用于保存具有映射关系的数据:key-value
  2. Map中的key和value可以是任意引用类型的数据,会封装到HashMap$Node
  3. Map中的key不可以重复,当有相同的key时,等价于替换value值
  4. Map中的value可以重复
  5. key和value都可以为null,但key为null只能有一个,value为null可以有多个
  6. 常用String类作为map的key
  7. key和value存在单向一对一的关系,即通过指定的key总能找到对应的value
  8. 一对key-value就是放在一个Node中的,Node实现了Entry接口,所以一对k-v也是一对Entry。

Map源码解读

map底层

  1. HashMap$Node node = newNode(hash, key, value, null);
  2. 为了方便程序员遍历,还会创建EntrySet集合,该集合存放元素的类型Entry,而一个Entry对象就有k,v。 EntrySet<Entry<K,V>>
  3. EntrySet中定义的类型是Map.Entry,但实际存放的是HashMap$Node
  4. Map.Entry提供重要方法:getKey();getValue()

Map接口常用方法

  1. put添加
  2. remove根据键删除映射关系
  3. get根据键获取值
  4. size获取元素个数
  5. isEmpty判断元素个数为0
  6. clear清除
  7. containsKey查找键是否存在

Map的遍历方式

Map map = new HashMap();
map.put("赵敏", "张无忌");
map.put("金美英王", "白眉鹰王");
map.put("江直树", "袁湘琴");
map.put("迪丽热巴", "龚俊");

Set keySet = map.keySet();
System.out.println("=====第一种遍历方式======");
for (Object ob : keySet) {
    System.out.println(ob + "-" + map.get(ob));
}
System.out.println("=====第二种遍历方式======");
Iterator iterator = keySet.iterator();
while (iterator.hasNext()) {
    Object ob = iterator.next();
    System.out.println(ob + "-" + map.get(ob));
}
System.out.println("=====第三种遍历方式======");
Collection values = map.values();
for (Object ob : values) {
    System.out.println(ob);
}
System.out.println("=====第四种遍历方式======");
Set entrySet = map.entrySet();
for (Object ob : entrySet) {
    Map.Entry entry = (Map.Entry) ob;
    System.out.println(entry.getKey() + "-" + entry.getValue());
}

System.out.println("=====第五种遍历方式=====");
Iterator iterator1 = entrySet.iterator();
while (iterator1.hasNext()) {
   Object ob = iterator1.next();
   Map.Entry entry = (Map.Entry) ob;
   System.out.println(entry.getKey() + "-" + entry.getValue());
}

Map接口实现类HashMap

  1. HashMap是Map接口使用频率最高的实现类。
  2. 与HashSet一样不保证映射的顺序。因为底层是以hash表的方式存储的。
  3. HashMap没有实现同步,因此是线程不安全的。

HashMap底层实现机制(和HashSet相同)

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

Hashtable

  1. 存放的元素是键值对:K-V
  2. Hashtable的键值都不能为null,否则会抛出NullPointerException
  3. Hashtable使用方法基本和HashMap一样
  4. Hashtable是线程安全的,HashMap是线程不安全的。

Hashtable底层实现机制

  1. 底层有数组Hashtable$Entry[],初始化大小为11
  2. 临界值 threshold 8 = 11 * 0.75
  3. 扩容:当count>=threshold时就进行扩容
  4. 按照 int newCapacity = (oldCapacity << 1) + 1的大小进行扩容
    对比

Properties(Hashtable的子类)

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

总结(开发中如何选择集合实现类)

主要取决于业务操作特点,然后根据集合类特性进行选择,分析如下:

  1. 先判断存储的类型(一组单列对象或一组双列键值对)
  2. 一组单列对象:Collection接口
  • 允许重复:List
    • 增删多:LinkedList(底层维护了一个双向链表)
    • 改查多:ArrayList(底层维护Object类型的可变数组)
  • 不允许重复:Set
    • 无序:HashSet(底层是哈希表,jdk7是数组+链表,jdk8是数组+链表+红黑树)
    • 排序:TreeSet
    • 插入和取出顺序一致:LinkedHashSet(数组+双向链表)
  1. 一组双列键值对:Map
    • 键无序:HashMap(底层是哈希表,jdk7是数组+链表,jdk8是数组+链表+红黑树)
    • 键排序:TreeMap
    • 键插入和取出顺序一致:LinkedHashMap
    • 读取文件:Properties

其他知识点

  • transient关键字用于,当类的某些属性需要序列化,有些不需要序列化时,只需要实现Serilizable接口,将不需要序列化的属性前添加关键字transient,序列化对象的时候,这个属性就不会序列化到指定的目的地中。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值