JAVA 集合知识点整理
对JAVA 集合这部分知识还是应该多了解学习因为常用和常被面,出于两方面原因对其最近又重新学习了一下,整理如一下与大家分享
一、java 集合可以分为两大阵营 Collection和Map
集合结构分为两种数组和链表:
查多修改少时用数组,查少修改多时用链表,因为数组插入、删除会移动其后面所有元素;
链表插入修改只修改前后2个元素,但链表查询较慢需要遍历所有元素;
数组用于查询多(根据索引),插入删除节点改少场景;
链表用于查询少,插入删除较多场景
Collection和Map结构图进行整体了解
Collection结构图
Map 结构图
二、集合特点整理
2.1 ArrayList
List接口:不唯一,有序
底层:由一个 object数组和size 两个重要属性,在add时初始化长度10,在超过时扩容到原来1.5倍,所以如果已知数组长度可以 初始化时定给定长度:
List list =new ArrayList(10);
Arraylist 核心属性
/** * The array buffer into which the elements of the ArrayList are stored. * The capacity of the ArrayList is the length of this array buffer. Any * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA * will be expanded to DEFAULT_CAPACITY when the first element is added. */ transient Object[] elementData; // non-private to simplify nested class access /** * The size of the ArrayList (the number of elements it contains). * * @serial */ private int size;
2.2 LinkedList
LinkedList是双向链表实现的List
LinkedList是非线程安全的
LinkedList元素允许为null,允许重复元素
LinkedList是基于链表实现的,因此插入删除效率高,查找效率低(虽然有一个加速动作)
LinkedList是基于链表实现的,因此不存在容量不足的问题,所以没有扩容的方法
LinkedList还实现了栈和队列的操作方法,因此也可以作为栈、队列和双端队列来使用
优点:因为是链表不会扩容增加速度,中间位置删除、插入元素不用移动后面所有元素,
List 中 有序怎样存放怎样取 FIFO 元素可以重复
|-- ArrayList:底层的数据结构使用的是数组结构(数组长度是可变的百分之五十延长)(特点是查询很快,但增删较慢)线程不同步
|-- LinkedList:底层的数据结构是链表结构(特点是查询较慢,增删较快)
2.3 set
唯一,无序
Set set=new HashSet(); 数组+链表 先比hashCode、再比 equals
Set<Person> set=new HashSet<Person>(); //可以重写hashCode、再比 equals 这样才能体现其特性 唯一
HashCode 相同 equals 可能相同
HashCode 不同 equals 一定不同 用hashCode 是因为要提高比较检索速度
2.3 LinkedHashSet
Set实现类之二:LinkedHashSet
LinkedHashSet 是 HashSet 的子类
LinkedHashSet 根据元素的 hashCode 值来决定元素的存储位置,但它同时使用双向链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
LinkedHashSet插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
LinkedHashSet 不允许集合元素重复。
2.4
Set实现类之三:TreeSet
TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。
TreeSet底层使用红黑树结构存储数据
TreeSet 两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。
三、同步容器
Collections.Syncnoized(new ArrayList());
ConcurrentHashMap:减少锁的粒度 及将原来一把锁变成多把锁 锁片断,性能高、线程安全
比 Collections.SyncnozedMap(new HashMap());性能好
ConcurrentHashMap:分段锁的机制,实现了多线程写入时的线程安全,也提高了多线程情况下的访问效率
3.1 CopyOnwirteArrayList
COW 写时复制容器 copy on write, 实现读写分离,通过复制一个新容器进行添加新元素,当添加完后将变量指向新复制对象, 应用场景:读多写少
CopyOnwirteArrayList 用于替代ArrayList,在add()方法中对有reetrentLock 锁,通过复制一个新容器进行添加新元素,当添加完后将变量指向新复制对象
3.2 数据构之 Queue
继承queue,继承Collection<E>
队列:特点:先进先出 (FIFO)
Queue:分BlockingQueue-接口:实现BlockingArrayQueue(需要指定长度)、SyncnoziedQueue、LinkedBlockingQueue、
阻塞队列:
当出队时,如果没有会阻塞等待,当有时再出队
BlockingQueue 继承了Queue接口。
队列是一种数据结构.它有两个基本操作:在队列尾部加人一个元素,和从队列头部移除一个元素就是说,队列以一种先进先出的方式管理数据,如果你试图向一个 已经满了的阻塞队列中添加一个元素或者是从一个空的阻塞队列中移除一个元索,将导致线程阻塞.在多线程进行合作时,阻塞队列是很有用的工具。
add 增加一个元索 如果队列已满,则抛出一个IIIegaISlabEepeplian异常
remove 移除并返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
element 返回队列头部的元素 如果队列为空,则抛出一个NoSuchElementException异常
offer 添加一个元素并返回true 如果队列已满,则返回false
poll 移除并返问队列头部的元素 如果队列为空,则返回null
peek 返回队列头部的元素 如果队列为空,则返回null
put 添加一个元素 如果队列满,则阻塞
take 移除并返回队列头部的元素 如果队列为空,则阻塞
put 是如何阻塞的源码说明
/** Condition for waiting puts */ private final Condition notFull;
lock = new ReentrantLock(fair);
notEmpty = lock.newCondition();
notFull = lock.newCondition();
进行阻塞 【notFull.await()】
** * Inserts the specified element at the tail of this queue, waiting * for space to become available if the queue is full. * * @throws InterruptedException {@inheritDoc} * @throws NullPointerException {@inheritDoc} */ public void put(E e) throws InterruptedException { checkNotNull(e); final ReentrantLock lock = this.lock; lock.lockInterruptibly(); try { while (count == items.length) notFull.await(); enqueue(e); } finally { lock.unlock(); } }
小伙伴们 以上是近期整理如有疑问欢迎一起讨论分析。