android基础之Map系列

本文深入探讨了Java中的Map接口及其几种实现,包括HashMap、HashTable、LinkedHashMap、TreeMap和ConcurrentHashMap。HashMap是最常用的选择,提供快速访问但线程不安全;ConcurrentHashMap则为多线程环境提供了高效并发解决方案;而LinkedHashMap保持插入顺序,TreeMap则按键排序。了解它们的区别和适用场景对于选择合适的Map实现至关重要。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

数组:内存存储连续 占用内存多 寻址容易,时间复杂度: 索引查找 (O(1)),按值查找(O(log(2)n)

链表: 内存存储不连续 占用内存少 插入与删除方便,时间复杂度(O(n)) ,

为了结合数组寻址容易与链表的插入删除容易,HashTable应运而生;

 

java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap 

Hashtable LinkedHashMap 和TreeMap.

HashMap: 数据结构:数组+链表+红黑树(或称之为链表的数组),HashMap里面有一个Entry类(key,value,next),可以理解为其存储结构是一个线性数组(Entry[]),

 

put():

根据key的hashCode得到hash值,然后hash对Entry[].length取模得到下标index,在数组的index 下标位置处添加value,当然这时就要注意当hash值重复时就会发生hash冲突。

解决Hash冲突: 假设Entry[0] = A;进来了一个键值对B,其index值与A相同,这时让B.next = A;

Entry[0] = B;...,这时就解决了hash冲突。也就是说数组中存储的是最后插入的元素。

get():

根据key.hashCode得到hash值对Entry[]取模得到index,这时根据index得到所对应的链表或红黑树,然后根据equea()判断key值是否相等,相等时返回该值,不相等时判断下一个元素,直到该链表中再无元素。

 

区别:null值,安全性,同步,速度

 

总结:

 

Map: map用于存储键值对,根据键得到值,键不允许重复(重复就覆盖了),但允许值重复。

 

 

HashMap:hashMap是一个最常用的Map。它根据键的Hashcode值存储数据,根据键可以直接得到它的值,具有很快的访问速度,遍历时,取得数据的顺序都是完全随机的。HashMap只允许一条记录的键为null,允许多个记录的值为null。HashMap不支持线程的同步,即任一时刻可以有多个线程操作HashMap;可能会导致数据不一致。(解决方法:使用SynchronizedMap或者ConcurrentHashMap)所以线程不安全,多个线程无法共享一个HashMap.。

 

WeakHashMap:WeakHashMap是一种改进的HashMap,它对key实行“弱引用”,当一个key不被外界所引用,则该Key会被GC回收。

 

HashTable: 与HashMap类似,不同点:不允许键或者值为null,synchronized,支持线程同步,线程安全,多个线程可以共享一个HasTable,即任一时刻,只允许一个线程能写HashTable,这也就导致了HashTable在写入时比较慢。

 

LinkedHashMap:LinkedHashMap是HashMap的一个子类,保存了记录的插入顺序,在Iterator遍历LinkedHashMap时,先得到的记录一定是先插入的,也可以在构造时用带参数,按照应用次序排序。在遍历时比HashMap慢,不过有种情况例外,当HashMap的容量很大,实际数据较少时,遍历起来可能会比LinkedHashMap慢,因为LinkedHashMap的遍历速度只与实际数据有关,与容量无关,而HashMap的遍历速度与容量有关。

 

TreeMap:TreeMap实现了SortMap的接口,能够将它保存的记录按照键排序,默认是升序排序。也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。

 

SynchronizedMap:hashMap存在线程安全问题,因此,在Collections类提供了一个方法返回一个同步版本的HashMap用于多线程环境,该方法返回一个SynchronizedMap实例。SynchronizedMap类是定义在Collection中的一个静态内部类。他实现了Map接口,并对其中的每一个方法实现,通过Synchronized关键字进行了同步控制。但还是存在潜在的安全问题。

 

 

 

ConcurrentHashMap:ConcurrentHashMap提供了HashTable和HashMap以及SynchronizedMap中所不同的锁机制。比起SynchronizedMap,它提供了好得多的并发性。多个读操作几乎总可以并发执行,同时进行的读和写操作也能并发执行,而同时进行的写操作仍然可以不时的并发执行。HashTable采用的锁机制是一次锁定整个hash表,从而同一时刻只能由一个线程对其进行操作;

ConrrentHashMap采用的锁机制是每一次锁定一个桶。

ConcurrentHahMap默认将hash表分为16个桶,诸如get、put、remove等寻常操作只锁当前需要用到的桶。这样一来,原本只能一个线程进入,现在却能同时有16个写线程进行执行,并发性的提升显而易见。前面所说的16个线程指的是写线程,而读操作基本不需要用到锁。只有在size等操作时才会锁定整个表。

 

在迭代方面,ConcurrentHashMap使用了一种不同的迭代方式。在这种迭代方式中,当Iterator被创建后集合在再发生改变就不会再是抛出ConcurrentModificationException,取而代之的是在改变时new新的数据从而不影响原有的数据,iterator完成后再将头指针替换为新的数据,这样Iterator线程就可以使用原来老的数据,从而写线程也可以并发的完成改变。

 

 

 

 

 

Hashmap与LinkedHashMap与TreeMap使用场景:

一般情况下,我们用的最多的是HashMap,在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按自然顺序或自定义顺序遍历键,那么TreeMap会更好。如果需要输出的顺序和输入的相同,那么用LinkedHashMap 可以实现,它还可以按读取顺序来排列.

 

Hashmap与SynchronizedMap与ConcurrentHashMap使用场景:

一般情况下使用HashMap,但是HashMap线程不安全,所以在多线程的场景下使用SynchronizedMap,但是SynchronizedMap也存在一些潜在的安全问题(如迭代时数据更改),这时我们拥有更好的选择concurrenthashMap。

 

扩展:

CopyOnWriteArrayList可以用于什么应用场景?

答:CopyOnWriteArrayList用于读多写少的并发场景,比如白名单、黑名单。

CopyOnWrite容器即写时复制的容器。通俗的理解是当我们往一个容器添加元素的时候,不直接往当前容器添加,而是先将当前容器进行Copy,复制出一个新的容器,然后新的容器里添加元素,添加完元素之后,再将原容器的引用指向新的容器。这样做的好处是我们可以对CopyOnWrite容器进行并发的读,而不需要加锁,因为当前容器不会添加任何元素。所以CopyOnWrite容器也是一种读写分离的思想,读和写不同的容器。

CopyOnWriteArrayList(免锁容器)的好处之一是多个迭代器同时遍历和修改这个列表时,不会抛出ConcurrentModificationException。在CopyOnWriteArayList中,写入将会导致创建整个底层数组的副本,而源数组将保留在原地,使得复制的数组在被修改时,读取操作可以安全地执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值