大神图镇楼
这是从隔壁大神那里拿来的图,大神就是大神,做的图一目了然,JAVA常用的容器都已经列出来了,主要分为三种:List、Set、Map.
其他的容器类型基本上只出现在习题里面。
List
虽然据说List常用的集合有ArrayList和LinkedList,但是第二种使用的情况很少见,一般来说无脑用第一种就行了。
ArrayList底层是数组,LinkedList底层是链表。数组遍历速度快,LinkedList增删元素快。
在工作中,主要的需求是储存与查找(遍历),增删的需求比较少,更何况ArrayList的增删速度也不差,综上所述,还是无脑用ArrayList。
如果考虑线程安全的问题,可以看看CopyWriteOnArrayList,实际开发用得不多,但我觉得可以了解一下它的思想(CopyWriteOn),这个思想在Linux/文件系统都有用到。
Set
Set集合下最常见的集合类有三个:HashSet、TreeSet、LinkedHashSet
说到这里,我有必要提一下数据结构的知识,虽然在Java中没有直接使用链表、栈、队列等这样原始的数据结构,而是封装成了容器的形式供我们使用,但是这些容器的底层其实还是那些原生数据结构。
Array:数组
Hash: 散列表
Linked:链表
Tree:树
Queue:队列
在java中封装好的容器也保留了原始数据结构的特征。
比如:
HashSet:既保留了Set的不可重复的特征,又具有Hash表无序且查询快的特征。
TreeSet:有排序的Set集合
List和Set都是集合,一般来说:如果我们需要保证集合的元素是唯一的,就应该想到用Set集合。
比如说:现在要发送一批消息给用户,我们为了减少「一次发送重复的内容给用户」这样的错误,我们就用Set集合来保存用户的userId/phone
自然地,首先要保证最上游的那批用户的userId/phone是没有重复的,而我们用Set集合只是为了做一个兜底来尽可能避免重复发送的问题。
一般我们在开发中最多用到的也就是HashSet。TreeSet是可以排序的Set,一般我们需要有序,从数据库拉出来的数据就是有序的,可能往往写order by id desc比较多。而在开发中也很少管元素插入有序的问题,所以LinkedHashSet一般也用不上。
如果考虑线程安全的问题,可以考虑CopyOnWriteArraySet,用得就更少了(这是一个线程安全的Set,底层实际上就是CopyWriteOnArrayList)
TreeSet和LinkedHashSet更多的可能用在刷算法的时候。
Map
Map集合最常见的子类也有三个:HashMap、LinkedHashMap、TreeMap
如果考虑线程安全问题,应该想到的是ConcurrentHashMap,当然了Hashtable也要有一定的了解,因为面试实在是问得太多太多了。
HashMap在实际开发中用得也非常多,只要是key-value结构的,一般我们就用HashMap。LinkedHashMap和TreeMap用的不多,无脑用HashMap就行了。
ConcurrentHashMap在实际开发中也用得挺多,我们很多时候把ConcurrentHashMap用于本地缓存,不想每次都网络请求数据,在本地做本地缓存。监听数据的变化,如果数据有变动了,就把ConcurrentHashMap对应的值给更新了。
那么问题来了,什么时候用线程安全的容器,其实大部分情况下都用不到的,因为我们通常都会把容器放进方法里储存在每个线程的栈中,只有共享的成员变量有可能会遇到线程不安全的情况。
只要涉及到多个线程操作一个共享变量的时候,就要考虑是不是要用线程安全的集合类。