标签:
这篇文章总结了所有的Java集合(Collection)。主要介绍各个集合的特性和用途,以及在不同的集合类型之间转换的方式。
Array是Java特有的数组。在你知道所要处理数据元素个数的情况下非常好用。java.util.Arrays
包含了许多处理数据的实用方法:
Array
转换成 List
。可以作为其他集合类型构造器的参数。、
Arrays.deepHashCode:Arrays.equals/hashCode
的高级版本,支持子数组的操作。equals
方法(数组对象中没有重写equals()
方法,所以这个方法之比较引用而不比较内容)。这个方法集合了Java 5的自动装箱和无参变量的特性,来实现将一个变量快速地传给 equals()
方法——所以这个方法在比较了对象的类型之后是直接传值进去比较的。hashCode()
不可用)。这个方法集合了Java 5的自动装箱和无参变量的特性,来实现将一个变量快速地传给 Arrays.hashcode
方法——只是传值进去,不是对象。如果想要复制整个数组或其中一部分到另一个数组,可以调用 System.arraycopy
方法。此方法从源数组中指定的位置复制指定个数的元素到目标数组里。这无疑是一个简便的方法。(有时候用 ByteBuffer bulk复制会更快。可以参考这篇文章).
最后,所有的集合都可以用T[] Collection.toArray( T[] a )
这个方法复制到数组中。通常会用这样的方式调用:
return coll.toArray( new T[ coll.size() ] );
这个方法会分配足够大的数组来储存所有的集合,这样 toArray
在返回值时就不必再分配空间了。
这一部分介绍的是不支持多线程的集合。这些集合都在java.util
包里。其中一些在Java 1.o的时候就有了(现在已经弃用),其中大多数在Java 1.4中重新发布。枚举集合在Java 1.5中重新发布,并且从这个版本之后所有的集合都支持泛型。PriorityQueue
也在Java 1.5中加入。非线程安全的集合架构的最后一个版本是ArrayDeque
,也在Java 1.6中重新发布了。
List
集合实现。由一个整形数字或数组存储了集合的大小(数组中第一个没有使用的元素)。像所有的List
集合一样,ArrayList
可以在必要的时候扩展它的大小。ArrayList访问元素的时间开销固定。在尾部添加元素成本低(为常数复杂度),而在头部添加元素成本很高(线性复杂度)。这是由ArrayList
的实现原理——所有的元素的从角标为0开始一个接着一个排列造成的。也就是说,从要插入的元素位置往后,每个元素都要向后移动一个位置。CPU缓存友好的集合是基于数组的。(其实也不是很友好,因为有时数组会包含对象,这样存储的只是指向实际对象的指针)。Deque
实现:每一个节点都保存着上一个节点和下一个节点的指针。这就意味着数据的存取和更新具有线性复杂度(这也是一个最佳化的实现,每次操作都不会遍历数组一半以上,操作成本最高的元素就是数组中间的那个)。如果想写出高效的LinkedList
代码可以使用ListIterators
。如果你想用一个Queue/Deque
实现的话(你只需读取第一个和最后一个元素就行了)——考虑用ArrayDeque
代替。ArrayList
版本。现在直接用ArrayList
代替了。Deque
是基于有首尾指针的数组(环形缓冲区)实现的。和LinkedList
不同,这个类没有实现List
接口。因此,如果没有首尾元素的话就不能取出任何元素。这个类比LinkedList
要好一些,因为它产生的垃圾数量较少(在扩展的时候旧的数组会被丢弃)。Deque
来代替(ArrayDeque
比较好)。poll/peek/remove/element
会返回一个队列的最小值。不仅如此,PriorityQueue
还实现了Iterable
接口,队列迭代时不进行排序(或者其他顺序)。在需要排序的集合中,使用这个队列会比TreeSet
等其他队列要方便。Map
实现。只是将一个键和值相对应,并没有其他的功能。对于复杂的hashCode method
,get/put
方法有固定的复杂度。Map
。因为键的数量相对固定,所以在内部用一个数组储存对应值。通常来说,效率要高于HashMap
。HashMap
的同步版本,新的代码中也使用了HashMap
。Map
版本,它违背了一般Map
的规则:它使用 “==” 来比较引用而不是调用Object.equals
来判断相等。这个特性使得此集合在遍历图表的算法中非常实用——可以方便地在IdentityHashMap
中存储处理过的节点以及相关的数据。HashMap
和LinkedList
的结合,所有元素的插入顺序存储在LinkedList
中。这就是为什么迭代LinkedHashMap
的条目(entry)、键和值的时候总是遵循插入的顺序。在JDK中,这是每元素消耗内存最大的集合。Map
需要实现equals
方法和Comparable/Comparator
。compareTo
需要前后一致。这个类实现了一个NavigableMap
接口:可以带有与键数量不同的入口,可以得到键的上一个或者下一个入口,可以得到另一Map
某一范围的键(大致和SQL的BETWEEN
运算符相同),以及其他的一些方法。Map
通常用在数据缓存中。它将键存储在WeakReference
中,就是说,如果没有强引用指向键对象的话,这些键就可以被垃圾回收线程回收。值被保存在强引用中。因此,你要确保没有引用从值指向键或者将值也保存在弱引用中m.put(key, new WeakReference(value))
。HashMap
的Set
实现。其中,所有的值为“假值”(同一个Object
对象具备和HashMap
同样的性能。基于这个特性,这个数据结构会消耗更多不必要的内存。Set
。Java的每一个enum
都映射成一个不同的int
。这就允许使用BitSet
——一个类似的集合结构,其中每一比特都映射成不同的enum
。EnumSet
有两种实现,RegularEnumSet
——由一个单独的long
存储(能够存储64个枚举值,99.9%的情况下是够用的),JumboEnumSet
——由long[]
存储。BitSet
处理一组密集的整数Set
(比如从一个预先知道的数字开始的id集合)。这个类用 long[]
来存储bit
。HashSet
一样,这个类基于LinkedHashMap
实现。这是唯一一个保持了插入顺序的Set
。HashSet
类似。这个类是基于一个TreeMap
实例的。这是在单线程部分唯一一个排序的Set
。就像有专门的java.util.Arrays
来处理数组,Java中对集合也有java.util.Collections
来处理。
第一组方法主要返回集合的各种数据:
ClassCastException
异常。这个功能可以防止在运行的时候出错。//fixmeput
或update
这样的复合操作)第二组方法中,其中有一些方法因为某些原因没有加入到集合中:
Arrays.binarySearch
功能相同。String.indexOf(String) / lastIndexOf(String)
方法类似——找出给定的List
中第一个出现或者最后一个出现的子表。Collections.reverseOrder
比较器。List
集合中的节点,可以给定你自己的生成器——例如 java.util.Random / java.util.ThreadLocalRandom or java.security.SecureRandom
。这一部分将介绍java.util.concurrent
包中线程安全的集合。这些集合的主要属性是一个不可分割的必须执行的方法。因为并发的操作,例如add
或update
或者check
再update
,都有一次以上的调用,必须同步。因为第一步从集合中组合操作查询到的信息在开始第二步操作时可能变为无效数据。
多数的并发集合是在Java 1.5引入的。ConcurrentSkipListMap / ConcurrentSkipListSet
和 LinkedBlockingDeque
是在Java 1.6新加入的。Java 1.7加入了最后的 ConcurrentLinkedDeque
和 LinkedTransferQueue
listeners/observers
集合。Delayed
元素的集合。元素只有在延时已经过期的时候才能被取出。队列的第一个元素延期最小(包含负值——延时已经过期)。当你要实现一个延期任务的队列的时候使用(不要自己手动实现——使用ScheduledThreadPoolExecutor
)。ReentrantLock-s
。transfer
方法,可以让生产者直接给等待的消费者传递信息,这样就不用将元素存储到队列中了。这是一个基于CAS操作的无锁集合。PriorityQueue
的无界的版本。Queue
接口的话,通过Exchanger
类也能完成响应的功能。get
操作全并发访问,put
操作可配置并发操作的哈希表。并发的级别可以通过构造函数中concurrencyLevel
参数设置(默认级别16)。该参数会在Map
内部划分一些分区。在put
操作的时候只有只有更新的分区是锁住的。这种Map
不是代替HashMap
的线程安全版本——任何 get-then-put
的操作都需要在外部进行同步。ConcurrentNavigableMap
实现。本质上这种集合可以当做一种TreeMap
的线程安全版本来使用。ConcurrentSkipListMap
来存储的线程安全的Set
。CopyOnWriteArrayList
来存储的线程安全的Set
。Objects
类不同)。如果想要了解更多关于Java集合的知识,推荐阅读以下书籍:
单线程 | 并发 | |
Lists |
|
|
Queues / deques |
|
|
Maps |
|
|
Sets |
|
|
标签:
原文地址:http://www.cnblogs.com/leetieniu2014/p/5794131.html