Map

一、获取key和value

获取key:map.keySet(),获取map中所有的key,返回一个Set集合存储所有的键;

获取value:Map.values()或者map.entrySet()

  • Map.values(),方法用来获取 Map 集合中的所有value,将值存放在一个Set集合中

  • map.entrySet()✅,同时获取map的key和value,只需要查询一次;然后for循环key,根据key获取value

获取key和value:map.entrySet(),同时查询map的key和value,只需要查询一次,然后可for循环entry获取key和value

二、常用map之间的区别和使用场景

2.1. hashMap, hashtable,linkedHashMap,treeMap之间的区别

(1)hashMap: 以键值对尽心存储,线程不安全,无序,可以允许一个null键和多个null,可以通过键直接获取对应值,所以查询效率高

(2) concurrentHashMap:

(3) linkedHashMap: 它是hashmap的子集,在继承hashmap的同时添加了一个排序字段,记录插入的顺序,通过for循环可以有序的输出

(4) treemap: 它实现了sortedmap,所以可以进行集合排序输出,默认是通过key进行的升序进行排序,也可以自定义进行排序

(5) hashtable(最好不用): 它也是通过键值对进行存储,无序,但是他是线程安全的,绝大多数方法使用synchronized修饰,不允许null键和null值,一般用于多线程并发情况,但是在最新的代码中最好不使用,在单线程中使用hashmap效率快,在多线程并发下,使用ConcurrentHashMap效率更快

2.2. 使用场景

当程序是单线程,且对集合输出的排序没有确切要求时使用hashMap

当程序是多线程并发情况,并且不需要排序,最好使用ConcurrentHashMap

当程序中需要先进先出时,我们则要使用linkedHashMap

当程序中需要对于集合进行特殊化排序时,我们即可使用TreeMap

对比项

HashMap

ConcurrnetHashMap

HashTable(不用)

线程安全

非线程安全

线程安全

线程安全

效率

最高

键和值

允许为null

允许为null

都不允许

使用选择

普通map

需要线程安全

 

 2.3 HashMap和HashTable

  • HashMap是非线程安全的,HashTable是线程安全的(内部的方法基本都经过synchronized修饰,其实是对对象加锁,锁住的都是对象整体,当Hashtable的大小增加到一定的时候,性能会急剧下降,因为迭代时需要被锁定很长的时间)
  • HashMap的键和值都允许有null存在,而HashTable则都不行。
  • 因为线程安全、哈希效率的问题,HashMap效率比HashTable的要高(HashTable效率低所以不怎么使用)。
  • HashMap默认初始化数组的大小为16,扩容时乘2,使用位运算取得哈希,效率高于取模;jdk8之后,如果链表的长度大于8,这个单向链表就会转换为红黑树;如果链表长度小于6位,就会从红黑树转换为链表。数组扩容时,扩容的大小是原有数组的2倍;HashTable为11,扩容时为乘2加1,都是素数和奇数,这样取模哈希结果更均匀。

三、ConcurrentHashMap

3.1 线程安全

ConcurrentHashMap 的线程安全指的是:提供的原子性读写操作是线程安全的, 也就是put()、get()操作是线程安全的。即在ConcurrentHashMap的内部使用CAS保证了更新操作的原子性,在同一时间只有一个线程能够完成对值的更新。

3.2 ConcurrentHashMap为什么高效?

Hashtable低效主要是因为所有访问Hashtable的线程都争夺一把锁。如果容器有很多把锁,每一把锁控制容器中的一部分数据,那么当多个线程访问容器里的不同部分的数据时,线程之前就不会存在锁的竞争,这样就可以有效的提高并发的访问效率。这也正是ConcurrentHashMap使用的分段锁技术。将ConcurrentHashMap容器的数据分段存储,每一段数据分配一个Segment(锁),当线程占用其中一个Segment时,其他线程可正常访问其他段数据。

3.3 方法

  • put()

  • get()

  • size()

  • computeIfAbsent:Value不存在时才计算

  • computeIfPresent:Value存在时才计算

  • compute:计算并更新值

https://wizardforcel.gitbooks.io/modern-java/content/ch6.html

http://blog.tanpeng.net/2017/07/13/map-compute/

3.4 问题

1、get+put操作并非原子操作,会导致线程不安全

问题描述:https://blog.csdn.net/weixin_46539949/article/details/121114944

解决:synchronized或者computeIfAbsent

  • 1、synchronized代码块锁住map(效率低 )
  • 2、使用computeIfAbsent

四、HashMap

4.1方法

  • getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。语法为hashmap.getOrDefault(Object key, V defaultValue)

五、ImmutableMap

可以更简洁地创建Map对象并赋值;对象创建后不可变

5.1 特点

1.对不可靠的客户代码库来说,它使用安全,可以在未受信任的类库中安全的使用这些对象

2.线程安全的:immutable对象在多线程下安全,没有竞态条件

3.不需要支持可变性, 可以尽量节省空间和时间的开销. 所有的不可变集合实现都比可变集合更加有效的利用内存 (analysis)

4.可以被使用为一个常量,并且期望在未来也是保持不变的

5.2 使用

1.使用of方法
ImmutableMap.of("a", 1, "b", 2);

2、使用Builder类创建

Map<String,Object> immutableMap = new ImmutableMap.Builder<String,Object>()
    .put("k1","v1")
    .put("k2","v2")
    .build();

 

 

 

posted @   zhegeMaw  阅读(27)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示