1、集合的体系
为什么要了解list、set、map呢?
答:我们在编写程序的过程中经常会对容器中的元素进行增删改查,那么如何快速又准 确的定位到你想访问到的元素呢?就不得不提到我们的常用的单列结合Collection和双列集合Map,先通过这张图看看他们各自的体系。
2、单列集合Collection
(1)List(有序、可重复、可以有多个null)
① ArrayList
底层数据结构是数组,查询快,增删慢,线程不安全(线程不同步),效率高。
② LinkedList
底层数据结构是链表,查询慢,增删快,线程不安全(线程不同步),效率高。
③ Vector
底层数据结构是数组,查询快,增删慢,线程安全(线程同步),效率低。
(2)Set(无序、不可重复、只能有一个null)
① HashSet
底层数据结构是哈希表
LinkedHashSet
底层数据结构由链表和哈希表组成,由链表保证元素有序,由哈希表保证元素唯一。
② TressSet
底层数据结构是红黑树。(是一种自平衡的二叉树),根据比较返回值是否是0来 决定保证元素唯一性。
两种排序方式:
自然排序(元素具备比较性):让元素所属的类实现Comparable接口
比较器排序(集合具备比较性):让集合接收一个Comparable的实现类对象
3、双列集合Map
注:Map集合的数据结构仅仅针对键有效,与值无关。存储的是键值对形式的元素,键唯一,值可以重复。
(1) HashMap
底层数据结构是哈希表,线程不安全,效率高。
哈希表依赖两个方法:hashCode()和equals()
(2)LinkedHashMap
底层数据机构由链表和哈希表组成(由链表保证元素有序,由哈希表保证元素唯一)
(3)Hashtable
底层数据结构是哈希表,线程安全,效率低。
哈希表依赖的两个方法:hashCode()和equals()
(4)TreeMap
底层数据结构是红黑树(是一种自平衡的二叉树)
据比较的返回值是否为0来决定保证元素的唯一性。
两种排序方式:
自然排序(元素具备比较性):让元素所属的类实现Comparable接口
比较器排序(集合具备比较性):让集合接收一个Comparable的实现类对象
4、实现类之间的比较
(1)ArrayList和LinkedList
① 前者:基于数组实现,是数组队列,相当于动态数组;
后者:基于链表实现,双向链表结构,也可以当做堆栈、队列、双端队列
② 当随机访问List时(get和set操作),前者比后者的效率高,因为LinkedList是线性的 数据存储方式,所以要移动指针从前往后依次查找。
③ 当对数据进行增删的操作时(add和remove操作),LinkedList比ArrayList的效率高,因为ArrayList是数组,所以在进行增删操作时,会对操作点之后所有的数据的下标索引造成影响,需要进项数据的移动。
④ 从内存空间占用来看,ArrayList的空间浪费体现在会预留一定的容量空间,而LinkedList中存储的每个元素都需要存放前驱和后继的指针,空间占用会比ArrayList中的每个元素的多。
⑤ ArrayList和LInkedList都是线程不安全的。
(2)ArrayList和Vector
① 前者是线程不安全的,后者是线程安全的
② 在不需要保证线程安全时应使用ArrayList,因为Vector在同步操作上会消耗大量时间
(3)HashMap和HashTable
① HashMap没有对读写等操作进行锁保护,所以是线程不安全的,在多线程场景下会出现数据不一致的问题;而HashTable是线程同步的,所有的读写操作都进行了锁 (synchronize)保护,在多线程环境下没有安全问题。
② HashMap允许键和值是null,而Hashtable不允许键或者值是null。
③ HashMap的迭代器(lterator)是fail-fash迭代器,但是Hashtable的迭代器(enumerator)不是fail-fast的,如果其他线程对HashMap进行的添加/删除元素,将会抛出CoucurrentModificationException,但是迭代器本身的remove方法移除元素则不会抛出异常。
5、使用场景
上面介绍了各种类的优点和缺点,那么这些类究竟在什么场景下使用哪一个呢?一张图带你看明白
你改变代码,代码改变世界!!!