Java容器
以下是我整理的一些Java容器、部分接口和抽象
1、List
(1)、ArrayList和LinkList:一个是数组、一个是链表;所有的数据结构的物理存储也只有连续存储的数组和非连续存储的链表。
(2)、Vetor和stack:Vetor从jdk1.0就有的一个线程安全的数组,里面所有的方法都加了synchronized,但是大部分的时候程序都是单线程的所以性能较差。Stack是Vector的子类,也是方法都加了一个synchronized关键字的一个线程安全的栈。但是目前不推荐使用Vector以及它的子类Stack。可以使用LinkList或者ArrayDeque来实现栈。
(3)、CopyOnWriteArrayList:写时复制。因为在LinkList和ArrayList中有并发安全问题,所以引入了CopyOnWriteArrayList。它在写的时候会复制一个新List,然后在新的List中进行操作,修改完成后在把旧的List引用指向这个新的List,并且在写的时候会通过ReentrantLock进行加锁。所以CopyOnWriteArrayList可以实现读写并行,写写排队执行。
2、Set
(1)、HashSet、LinkHashSet:底层都是用了HashMap,LinkHashSet还维护了一个双向链表,使里面元素有序。
(2)、SortSet(接口)、TreeSet:SortSet是一个接口,TreeSet是它唯一的实现类,可以让元素自定义排序,底层通过红黑树实现元素有序,不能加入null值。
(3)、CopyOnWriteSet:一个线程安全的Set,可以参考上面的CopyOnWriteList。
(3)、ConcurrentSkipListSet:是一个线程安全并且有序的Set集合。HashSet是用HashMap实现的,ConcurrentSkipLsitSet是用ConcurrentSkipListMap实现的。因为只用到了Map中的key,而Map中的value又不能为空,所以用一个Boolean.TRUE对象作为value值。并且它是一个跳表,可以提高查询效率。
(4)、EnumSet:专为枚举设计的集合类,里面不能有null值
3、queue
(1)、Deque(接口):双端队列,可以快速的在队列头部和尾部进行删除和添加操作。所以即可以当栈使用也可以当队列使用。官方也推荐使用Deque来实现队列和栈的各种需求。Deque底层数据结构有两种,一个是链表一个是数组。
——ArrayDeque:采用了循环数组的形式实现了Deque。ArrayDeque是线程不安全的并且不允许放入null值。数组中有两个指针。head指向头部,tail指向尾部下一个空闲位置。每当插入后会检查是否还有空余位置,如果没有则扩容到原来的两倍。
——LinkList:它也实现了Deque接口
——BlockingDeque(接口)、LinkBlockingDeque:BlockingDeque接口实现了BlockingQueue、Deque、Queue接口。LinkBlockingDeque实现了BlockingDeque是线程安全的。
(2)、BlockingQueue(接口):它是线程安全的,可以实现多个生产者和多个消费者共同安全工作。并且里面操作有四种形式:抛出异常、返回null/false、无限期阻塞当前线程知道操作成功、有限期阻塞当前线程。增加了put 和 take方法,用于阻塞调用。
——ArrayBlockingQueue:由一个有限的数组实现,初始化后容量就不能更改,是一个FIFO队列。设置为公平队列,以FIFO顺序授予线程访问权限,避免线程饥饿。里面用一个ReentrantLock锁,存放和查找都用一个锁,不能并行操作。
——LinkBlockingQueue:基于链表实现FIFOBlockingQueue队列,可选定容量,默认是Integer.MAX_VALUE。和ArrayBlockingQueue不同的是存取操作时用两个锁来控制,大大提高了队列的吞吐量
——SynchronousQueue:是一个容量为0的队列,当有一个put线程时如果此时没有take线程,就会一直阻塞,直到有take线程过来取数据。take操作同理。
——PriorityBlockingQueue:支持优先级的无界阻塞队列,默认是自然排序。基于最小二叉堆实现,使用CAS来控制动态扩容,保证扩容操作不会阻take操作的执行。
——TransferQueue(接口) 、LinkTransferQueue:LinktTransferQueue是TransferQueue接口的唯一实现类。结合了LinkBlockingQueue和SynchronousQueue的优点。不需要大量的锁并且可以存储多个元素。LinkTransferQueue中当有put操作时会看有没有其他等待获取的线程,如果有直接将数据给这个线程并返回,如果没有就会一直阻塞。总的来说在LinkTransferQueue中消费者的能力决定生产者的速度。
(3)、PriorityQueue:优先级队列,底层数据结构是一个堆树
(3)、ConcurrentLinkedQueue:是一个线程安全的队列,不同于BlockingQueue,它是非阻塞的,底层用cas保证入队和出队的安全,但不保证遍历安全。
(3)、DelayQueue:延迟队列,也实现了BlockingQueue接口。每当放入一个数据后,会根据它们的过期时间排序,队头总是离过期时间最近的那个。当要获取队列元素时,会先查看队头是否有过期元素,有就取出来没有就返回null。
4、Map
(1)、HashMap、LinkHashMap:HashMap是无序的,而LinkHashMap是有序的。LinkHashMap是基于一个双向链表实现,里面有after、before两个属性来实现元素的有序性。
(2)、TreeMap:它是基于红黑树实现的,不允许有空值,默认按key值自然排序。
(3)、WeakHashMap:WeakHashMap和HashMap不同的是,它是基于弱引用,每次gc后里面的entry键值对可能就被回收,WeakHashMap就会自动清理被回收的Entry键值对。
(4)、IdentityHashMap:IdentityHashMap不允许key值重复,比较key值得方法是比较它们的hashcode是否相等。
(5)、ConcurrentHashMap:线程安全,使用了synchronized和cas实现。
(6)、ConcurrentSkipListMap:线程安全的跳表结构。