JAVA集合
简单介绍
- 集合类存放在Java.util包里面
- Collection接口是集合的根接口,Map是另一个接口,与Collection是相互独立的
- Collection中包括List、Set、和Queue,Map主要包括HashMap和TreeMap
数组与集合的区别
- 数组的长度是固定的,而集合的长度是可以自动扩容的
- 集合可以存储不同的类型元素,二数组只能存放单一的类型元素
- 数组中可以存放基本类型(8种)和引用类型,而集合中只能存放引用类型
List集合
ArrayList
- 默认的构造方法是创建一个初始容量为10的空数组,扩容机制:1.5倍
- 基于数组实现的,查询快,增删慢,线程不安全,效率高,可存储重复元素
LinkedList
- 基于链表(双向链表)实现的,查询慢,增删快,线程不安全,效率高,可以存储重复元素
- 特有的方法:addFirst(),addLast(),removeFirst(),removeLast(),getFirst(),getLast()
Vector
- 基于数组实现的,查询慢,增删快,线程安全,效率低
- 特有方法:addElement()(相当于add),elementAt()(相当于get)
ArrayList、LinkedList、Vector的区别
- ArrayList扩容后的容量是之前的1.5倍,然后把之前的数据拷贝到新建的数组中去。而Vector默认情况下扩容后的容量是之前的2倍。
- Vector可以设置容量增量,而ArrayList不可以。
- 扩容与capacityIncrement(容量增量)参数相关,若此参数大于0,则按该值扩增容量,否则,成倍扩增
Set集合
HashSet
- 按照Hash算法来存储集合中的元素,根据对象的哈希码确定对象的存储位置,具有良好的存取和查找性能。
- 元素无序且唯一,线程不安全,效率高,可以存储null元素,元素的唯一性是靠所存储元素类型是否重写hashCode()和equals()方法来保证的,如果没有重写这两个方法,则无法保证元素的唯一性。
- 实现唯一性的过程:
存储元素首先会使用hash()算法函数生成一个int类型hashCode散列值,然后已经的所存储的元素的hashCode值比较,如果hashCode不相等,则所存储的两个对象一定不相等,此时存储当前的新的hashCode值处的元素对象;如果hashCode相等,存储元素的对象还是不一定相等,此时会调用equals()方法判断两个对象的内容是否相等,如果内容相等,那么就是同一个对象,无需存储;如果比较的内容不相等,那么就是不同的对象,就该存储了
- HashSet中的元素是不重复的, HashSet采用哈希算法,底层用数组存储数据。默认初始化容量16,加载因子0.75。
LinkedHashSet
- 底层数据结构采用链表和哈希表共同实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。线程不安全,效率高。
- 根据元素hashCode值来决定元素存储位置,但它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的。
TreeSet
- TreeSet集合中的元素处于排序状态,主要按照红黑树的数据结构来存储对象
- TreeSet根据元素的实际大小进行排序,不同于List是按照元素插入顺序进行排序。
Queue
Queue接口是一个先入先出(FIFO)的数据结构,继承Collection接口,LinkedList(双向链表)实现了List和Deque接口。
Deque接口和ArrayDeque类
- Deque接口是Queue接口的子接口, Deque接口的实现类主要是LinkedList类(前面已学习)和ArrayDeque类。
- ArrayDeque类是使用可变循环数组来实现双端队列,该容器不允许放入null元素。
- ArrayDeque是Deque接口的一个实现,使用了可变数组,所以没有容量上的限制。
- ArrayDeque是线程不安全的,在没有外部同步的情况下,不能再多线程环境下使用。
- ArrayDeque是Deque的实现类,可以作为栈来使用,效率高于Stack;也可以作为队列来使用,效率高于LinkedList。
- 需要注意的是,ArrayDeque不支持null值。
PriorityQueue类
- PriorityQueue(优先队列)是Queue接口的实现类,其底层是堆实现的。每次插入或删除元素后都对队列进行调整,队列始终构成最小堆或最大堆。
- 优先队列不允许空值,而且不支持non-comparable(不可比较)的对象,比如用户自定义的类。优先队列要求使用Java Comparable和Comparator接口给对象排序,并且在排序时会按照优先级处理其中的元素。
- 优先队列的头是基于自然排序或者Comparator排序的最小元素。如果有多个对象拥有同样的排序,那么就可能随机地取其中任意一个。当我们获取队列时,返回队列的头对象。
- 优先队列的大小是不受限制的,但在创建时可以指定初始大小。当我们向优先队列增加元素的时候,队列大小会自动增加。
- PriorityQueue是非线程安全的,所以Java提供了PriorityBlockingQueue(实现BlockingQueue接口)用于Java多线程环境。
Map
- Map 没有继承 Collection 接口, Map 提供 key 到 value 的映射,你可以通过“键”查找“值”。
- 一个 Map 中不能包含相同的 key ,每个 key 只能映射一个 value
HashMap
- HashMap 最多只允许一条记录的键为 null,允许多条记录的值为 null。
- HashMap 根据键的 hashCode 值存储数据,大多数情况下可以直接定位到它的值,因而具有很快
的访问速度,但遍历顺序却是不确定的。 - HashMap 非线程安全,即任一时刻可以有多个线程同时写 HashMap,可能会导
致数据的不一致。如果需要满足线程安全,可以用 Collections 的 synchronizedMap 方法使
HashMap 具有线程安全的能力,或者使用 ConcurrentHashMap。 - 详解:HashMap详解
HashTable
- HashTable是同步的,这个类中的方法中添加了synchronized关键字,保证了HashTable是线程安全的
- HashTable不能存放空值,性能较差
- Hashtable 不建议在新代码中使用,不需要线程安全的场合可以用 HashMap 替换,需要线程安全的场合可以用 ConcurrentHashMap 替换
TreeMap
- TreeMap 实现 SortedMap 接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。
- 如果使用排序的映射,建议使用 TreeMap。
- 在使用 TreeMap 时, key 必须实现 Comparable 接口或者在构造 TreeMap 传入自定义的Comparator,否则会在运行时抛出 java.lang.ClassCastException 类型的异常。
LinkedHashMap
- 使用双向链表来维护键值对的次序
- LinkedHashMap 是 HashMap 的一个子类,保存了记录的插入顺序,在用 Iterator 遍历LinkedHashMap 时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序。