java中的集合概览 - 及各使用场景

两种存储结构

从底层存储来讲,只会有两种存储结构,线性和链表,不会有第三方种,把多个东西连结起来成为集合,要么粘在一起,要么链起来,要么又粘又链的连起来。

 

在内存里,粘起来是用内存连续实现,链起来则是数据对象自带一到多个索引,索引指向目标对象,形成链。

  • 线性,内存连续,读的快、遍历快,但写时候相对不太好用,写满需复制扩容、删除需整体移位。
  • 链表,链随意指向,物理上不用连续存储,没有初始内存大小和扩容的概念,删除和加元素改链的指向即可, 读取和遍历需要把整个链一链一链的摸过去。
  • 读多写少用线性, 写多读少用链表。 写多且读多的场景,考虑用分治法的hash分块,或二分法的二叉树。一般hash分块用线性头加链表体; 二叉树是链表的一种,加强版的平衡二叉树通过限制规则保证二分的相对均匀。

 

JDK中的集合体系

JDK中集合有很多实现类,各个类都有不同功能,总体来说是不同维度的组合, 对线性表、链表;对非同步、有锁同步、无锁同步; 对有序、无序;对数据进出方式,进行多维度的组合实现以应对不同场景, 集合体系很大对我们来说不是负担,底层还是那点东西,JDK帮我们把大部分的场景下使用的集合都规范化的做好了,这是一套完整的工具箱。

 

集合的主要成员

顶层有两巨头,Conllection、Map

Conllection向下又有三大战将 List、Set、Queue(新战将)

 

Map 的成员:HashTable(已废弃syn同步)、HashMap 、LinkedHashMap(有序)、SynchronizedMap(syn同步 )、ConcurrentHashMap(AQS同步) 、TreeMap(有序)、ConcurrentSkipListMap(AQS同步有序跳表)

List 的成员(都有序):Vector(已废弃syn同步)、ArrayList、LinkedList、SynchronizedList、Stack、CopeOnWriteList(特殊同步)

Set 的成员:HashSet、LinkedHashSet(有序)、SynchronizedSet(syn同步 )、TreeSet、ConcurrentSkipListSet(AQS同步有序跳表)、

Queue 的成员:ConcurrentLinkedQueue、LinkedBlockingQueue 、ArrayBolckingQueue、DelayQueue 、PriorityQueue 、SynchronusQueue 、TransferQueue

注:(已废弃)曾经使用过后来被废弃或取代,不考虑使用。 (syn同步)用Synchronized实现线程安全。(AQS同步)用AQS实现线程安全。

 

各个集合的特性及应用场景

Map系列

HashTable(syn同步) : jdk1.0最初的map,所有的读写方法都加上了synchronized关键字, 被SynchronizedMap取代。

HashMap : 所有方法没做同步处理,基于数组加链表实现,1.8之后当链表结构达到8个时候链表会转换为红黑树。 场景应用在无需考虑线程安全的情况下。

LinkedHashMap (有序): 继承并加强了HashMap在HashMap的基础上增加了排序的概念。保存了原始的元素插入顺序。性能与HashMap差异不大。

SynchronizedMap(syn同步) : Collections工具类之中的私有内部类, 调用Collections.synchronizedMap(Map<K,V> m), 将一个Map包装成线程安全的Map 。 与HashTable相比,都是加锁实现,但是锁的粒度更小,效率更高。

ConcurrentHashMap(AQS同步) : 用AQS自旋锁实现的线程安全Map。 线程安全场景选两个Map选哪个 ,参见多线程下选synchronized 还是 AQS , 一般情况下等待线程多且单任务执行慢选synchronized ,等待线程不多且单线程执行快选AQS, 关键点在于避免AQS的忙等。

TreeMap(有序):红黑树实现的有序map, 用在需要排序且数据量大,需要用到平衡二叉树的方式读写数据。

ConcurrentSkipListMap(有序、AQS同步):跳表结构、线程安全、有序, (跳表)多层分治法的实现,每层平均抽取关键元素索引,类似于省市县乡分层去找人。 场景用在数据量大,且需要线程安全。 红黑树+AQS的实现过于复杂,jdk中放弃实现,而使用跳表+AQS来代替。

 

 

List系列

List都是有序的,元素允许重复

Vector: jdk1.0最初的List实现,所有方法都上了synchronized锁。 已废弃,被SynchronizedList取代。

ArrayList:基于数组实现的List 。

LinkedList:基于链表实现的List 。

SynchronizedList: Collections工具类之中的私有内部类,调用synchronizedList(List<T> list),将List包装成线程安全的List。

CopeOnWriteList:线程安全,读时不加锁,写时加锁,同时复制原有数组,在新数组上处理写,再将原对象引用指向这个新的数组。 写的效率低,读的效率高。 应用在读特别多写特别少,且需要同步。

Stack:继承自Vertor,所有方法都上了synchronized锁, 扩展了栈的概念,提供后进先出、压入栈顶的操作方法,仅此而已。 考虑用Queue来代替

 

Set系列

元素不允许重复

HashSet: 数组+链表,1.8之后当链表结构达到8个时候链表会转换为红黑树 。 场景用在需要元素不重复、不需要考虑线程安全。

LinkedHashSet(有序):继承并加强了HashSet,增加了排序的概念。 保存了原始的元素插入顺序。 性能与HashSet差异不大。

SynchronizedSet(syn同步) : Collections工具类之中的私有内部类,将Set包装成线程安全的Set。

TreeSet(有序): 红黑树实现 。

ConcurrentSkipListSet(AQS同步、有序): 跳表结构、线程安全、有序, (跳表)多层分治法的实现,每层平均抽取关键元素索引,类似于省市县乡分层去找人。 场景用在数据量大,且需要线程安全。

 

Queue系列

jdk1.5才有了Queue的引入,为高并发场景而生。队列是遵循先进先出(First-In-First-Out)模式的。 Queue 也是继承自Collection,可以说是List的加强版,增加了很多多线程场景下的方法及实现。 先说下相对于List增加的多线程场景处理方法。

Queue接口,的定义的3个方法

offer() 往队列添加,会有返回值,加成功返回ture 失败返回false 不会再此给异常

peek() 去取,但不会移除元素 ,成功返回ture 失败返回false 不会再此给异常

poll() 去取,且移除元素 ,成功返回ture 失败返回false 不会再此给异常

 

BlockingQueue接口 ,在Queue接口上扩展了阻塞方法,这两个方法体现了阻塞的概念

put() 阻塞的,一定要着往里加, 加不进去等着

take() 阻塞的, 一定要拿出来一个, 拿不到就等着,知道队列里有元素了,拿到了为止

阻塞的底层实现用 Condition pake

 

ConcurrentLinkedQueue : AQS实现的线程安全的队列,也是最为基础的队列。 应用场景上没有阻塞或其他要求可以使用这个。

LinkedBlockingQueue(阻塞) : 实现了BlockingQueue接口, 用链表实现的,既然是链表,队列的容量就是无界的,可以放任意长度,调put()不会阻塞。

ArrayBolckingQueue(阻塞) : 实现了BlockingQueue接口, 用数组实现,固定长度的有界队列。 队列满了,放任务的put() 往里放会阻塞住。

DelayQueue(阻塞) : 也实现了 BlockingQueue ,无界。增加时间的概念,Delay 延迟的意思,即设定一个时间在多久后执行该任务。

PriorityQueue : 有优先级概念的队列,可以自行实现CompareTo方法,识别出元素的优先级。场景用在需要优先级处理的情况下,如根据等待时间、数据重要程度、紧急程度来设定优先级比较。

SynchronusQueue : 容量为0,不是用来存储元素的,用来线程通讯,该queue作为一个送件员,将数据给到另外一个线程。 场景用在一对线程手握手的传递资源。

TransferQueue : 也是用来交换的,但是概念会有点不一样,transfer()方法 , 一个线程往队列里放元素,会一直等到另外一个线程拿走,如果没人来拿放线程会一直阻塞。 场景用在放元素的线程必须明确知道元素被确认拿走,才能去做其它事情。


 

 

 

 

 

 

 

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值