Java中的集合主要分为三类:
Map、List、Set三者关系图
Set(集合)特点:存储的数据不保证有序(存在有序情况),不允许重复元素,可以存放空元素,但只允许一个空元素存在。
Set主要有三个实现类
set集合为什么不能重复?
set的两个主要实现类,TreeSet和HashSet,底层存储结构都是用的map,而且是将set需要存储的值放在map的key里的,present是一个空的object对象。
Set集合在调用add方法的时候,add方法会调用元素的hashCode方法和equals方法,判断元素是否重复。
根据add的数据的HashCode方法计算哈希值,如果集合中不存在的话就保存到集合中,如果存在哈希值(哈希碰撞)就用equals比较,如果为false就保存到集合中,否则就是重复值,
List的特征是其元素以线性方式存储,集合中可以存放重复对象。 List接口主要实现类包括:(参考文章:)
默认长度为0,第一次add的时候设置初始容量为10,超过10的话会扩容为原来的1.5倍+1,也就是15.+1
默认长度为0,第一次add的时候设置初始容量为10,超过10会扩容为原来的2倍,也就是20.
对于List的随机访问来说,就是只随机来检索位于特定位置的元素。 List 的 get(int index) 方法放回集合中由参数index指定的索引位置的对象,下标从“0” 开始。
排序方法:Collections.sort,Arrays.sort两种
Collections.sort方法底层就是调用的Arrays.sort方法,而Arrays.sort使用了两种排序方法,快速排序(快)和优化的归并排序(稳定)。
数据量小于47:使用插入排序,插入排序是稳定的
47-286 的数据量:根据数据类型选择排序方式。
Map 是一种把键对象和值对象映射的集合,它的每一个元素都包含一对键对象和值对象。 Map没有继承于Collection接口 从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。
Comparator
默认按照key升序排序)。TreeMap的特点在 于,你得到的结果是经过排序的。TreeMap是唯一的带有subMap()方法的Map,它可以返回一个子树。Map各个子类详解↓↓↓
HashMap是不是线程安全的?
线程不安全,
在jdk1.7中,在多线程环境下,扩容时会造成环形链(发生在扩容的时候)或者数据丢失(多线程修改数据的时候,因为HashMap底层是一个Entry数组,当发生hash冲突的时候,hashmap是采用链表的方式来解决的,在对应的数组位置存放链表的头结点。对链表而言,新加入的节点会从头结点加入。如果多个线程同时访问一个哈希映射,而其中至少一个线程从结构上修改了该映射,导致数据被覆盖)。
在jdk1.8中,在多线程环境下,会发生数据覆盖的情况。
ConcurrentHashMap跟HashMap、HashTable区别?
具体看:
线程安全方面:
hashMap是线程不安全的,
hashTable是线程安全的,实现线程安全的机制是使用Synchronized关键字修饰方法。
<JDK1.7>,
分段锁 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。
<JDK1.8>
使用的是优化的synchronized 关键字同步代码块 和 cas操作了维护并发
底层数据结构:
hashMap同hashTable;都是使用数组 + 链表结构
ConcurrentHashMap
<JDK1.7> :使用 Segment数组 + HashEntry数组 + 链表
<JDK1.8> :使用 Node数组+链表+ 红黑树
效率:
hashMap只能单线程操作,效率低下
hashTable使用的是synchronized方法锁,若一个线程抢夺了锁,其他线程只能等到持锁线程操作完成之后才能抢锁操作
《1.7》ConcurrentHashMap 使用的分段锁,如果一个线程占用一段,别的线程可以操作别的部分,
《1.8》简化结构,put和get不用二次哈希,一把锁只锁住一个链表或者一棵树,并发效率更加提升。
LinkedHashMap为什么能实现有序?
排序原理:LinkedHashMap复写了HashMap的newNode(hash, key, value, null) 方法,
由源码可知,put第一次的时候 tail 和 head 都赋值为第一次put的数据,从第二个开始每次都将 tail(尾) 设置 为当前值,同时记录before(前一个数据)是谁并通知前一个数据记录它的后一个数据为自己,以此类推。。。我们只需要知道head(头)是谁,就能知道下一个是谁,tail(尾)为最后一个数据。
举例:我们依次插入A、B、C三个数据
1、插入 A 用户,设置 tail 和 head 为 A。
2、插入 B 用户,设置 tail 为 B,记录B的Before(前一个)数据为 A,通知前一个数据 A,叫 A 记录它的 After(后一个)数据为 B。
3、以此类推 。。。
当我们查看数据的时候可以根据他们的链式关系知道先后顺序:A -> B -> C
容器内每个为之所存储的元素个数不同。
Collection类型者,每个位置只有一个元素。
Map类型者,持有 key-value pair,像个小型数据库。
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- nryq.cn 版权所有 赣ICP备2024042798号-6
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务