Java 中的集合

JAVA中的集合

在使用Java的时候,咱们都会遇到使用集合(Collection)的时候,可是Java API提供了多种集合的实现。html

总的说来,Java API中所用的集合类,都是实现了Collection接口,他的一个类继承结构以下:java

                  Collection<--List<--Vector
                  Collection<--List<--ArrayList
                  Collection<--List<--LinkedList
                  Collection<--Set<--HashSet
                  Collection<--Set<--HashSet<--LinkedHashSet
                  Collection<--Set<--SortedSet<--TreeSet
数组

Vector : 基于Array的List,其实就是封装了Array所不具有的一些功能方便咱们使用,它不可能不受Array的限制。性能也就不可能超越Array。所 以,在可能的状况下,咱们要多运用Array。另外很重要的一点就是Vector :sychronized”的,这个也是Vector和 ArrayList的惟一的区别。安全

ArrayList:同Vector同样是一个基于Array上的链表,可是不一样的是ArrayList不是同步的。因此在性能上要比Vector优越一些,可是当运行到多线程环境中时,可须要本身在管理线程的同步问题。数据结构

LinkedList:LinkedList不一样于前面两种List,它不是基于Array的,因此不受Array性能的限制。它每个节点(Node)都包含两方面的内容:1.节点自己的数据(data);2.下一个节点的信息(nextNode)。因此当对LinkedList作添加,删除动做的时候就不用像基于Array的List同样,必须进行大量的数据移动。只要更改nextNode的相关信息就能够实现了。这就是LinkedList的优点。多线程

List总结:异步

1. 全部的List中只能容纳单个不一样类型的对象组成的表,而不是Key-Value键值对。例如:[ tom,1,c ];性能

2. 全部的List中能够有相同的元素,例如Vector中能够有 [ tom,koo,too,koo ];spa

3. 全部的List中能够有null元素,例如[ tom,null,1 ];线程

4. 基于Array的List(Vector,ArrayList)适合查询,而LinkedList(链表)适合添加,删除操做。

HashSet:虽然Set同List都实现了Collection接口,可是他们的实现方式却大不同。List基本上都是以Array为基础。可是Set则是在HashMap的基础上来实现的,这个就是Set和List的根本区别。HashSet的存储方式是把HashMap中的Key做为Set的对应存储项。看看HashSet的add(Object  obj)方法的实现就能够一目了然了。
    public boolean add(Object obj)
    {
        return map.put(obj, PRESENT) == null;
    }

这个也是为何在Set中不能像在List中同样有重复的项的根本缘由,由于HashMap的key是不能有重复的

LinkedHashSet:HashSet的一个子类,一个链表。

TreeSet:SortedSet的子类,它不一样于HashSet的根本就是TreeSet是有序的。它是经过SortedMap来实现的。

Set总结:

1. Set实现的基础是Map(HashMap);

2.  Set中的元素是不能重复的,若是使用add(Object obj)方法添加已经存在的对象,则会覆盖前面的对象

为何要使用集合类 ?

当你事先不知道要存放数据的个数,或者你须要一种比数组下标存取机制更灵活的方法时,你就须要用到集合类。

 
理解集合类

集合类存放于java.util包中。
集合类存放的都是对象的引用,而非对象自己,出于表达上的便利,咱们称集合中的对象就是指集合中对象的引用(reference)。
集合类型主要有3种:set(集)、list(列表)和map(映射)。

(1)集
集(set)是最简单的一种集合,它的对象不按特定方式排序,只是简单的把对象加入集合中,就像往口袋里放东西
对集中成员的访问和操做是经过集中对象的引用进行的,因此集中不能有重复对象。
集也有多种变体,能够实现排序等功能,如TreeSet,它把对象添加到集中的操做将变为按照某种比较规则将其插入到有序的对象序列中。它实现的是SortedSet接口,也就是加入了对象比较的方法。经过对集中的对象迭代,咱们能够获得一个升序的对象集合。

(2)列表
列表的主要特征是其对象以线性方式存储,没有特定顺序,只有一个开头和一个结尾,固然,它与根本没有顺序的集是不一样的。
列表在数据结构中分别表现为:数组和向量、链表、堆栈、队列。
关于实现列表的集合类,是咱们平常工做中常常用到的,将在后边的笔记详细介绍。

(3)映射
映射与集或列表有明显区别,映射中每一个项都是成对的。映射中存储的每一个对象都有一个相关的关键字(Key)对象,关键字决定了对象在映射中的存储位置,检索对象时必须提供相应的关键字,就像在字典中查单词同样。关键字应该是惟一的。
关键字自己并不能决定对象的存储位置,它须要对过一种散列(hashing)技术来处理,产生一个被称做散列码(hash code)的整数值,

散列码一般用做一个偏置量,该偏置量是相对于分配给映射的内存区域起始位置的,由此肯定关键字/对象对的存储位置。理想状况下,散列处理应该产生给定范围内均匀分布的值,并且每一个关键字应获得不一样的散列码。

集合类简介
java.util中共有13个类可用于管理集合对象,它们支持集、列表或映射等集合,如下是这些类的简单介绍

集:
HashSet: 使用HashMap的一个集的实现。虽然集定义成无序,但必须存在某种方法能至关高效地找到一个对象。使用一个HashMap对象实现集的存储和检索操做是在固定时间内实现的.

TreeSet: 在集中以升序对对象排序的集的实现。这意味着从一个TreeSet对象得到第一个迭代器将按升序提供对象。TreeSet类使用了一个TreeMap.

列表:
Vector: 实现一个相似数组同样的表,自动增长容量来容纳你所需的元素。使用下标存储和检索对象就象在一个标准的数组中同样。你也能够用一个迭代器从一个Vector中检索对象。Vector是惟一的同步容器类!!当两个或多个线程同时访问时也是性能良好的。

Stsck: 这个类从Vector派生而来,而且增长了方法实现栈!一种后进先出的存储结构。

LinkedList: 实现一个链表。由这个类定义的链表也能够像栈或队列同样被使用。

ArrayList: 实现一个数组,它的规模可变而且能像链表同样被访问。它提供的功能相似Vector类但不一样步。


映射:
HashTable: 实现一个映象,全部的键必须非空。为了能高效的工做,定义键的类必须实现hashcode()方法和equal()方法。这个类是前面java实现的一个继承,而且一般能在实现映象的其余类中更好的使用。

HashMap: 实现一个映象,容许存储空对象,并且容许键是空(因为键必须是惟一的,固然只能有一个)。

WeakHashMap: 实现这样一个映象:一般若是一个键对一个对象而言再也不被引用,键/对象对将被舍弃。这与HashMap造成对照,映象中的键维持键/对象对的生命周期,尽管使用映象的程序再也不有对键的引用,而且所以不能检索对象。

TreeMap: 实现这样一个映象,对象是按键升序排列的。

Set和List都是由公共接口Collection扩展而来,因此它们均可以使用一个类型为Collection的变量来引用。这就意味着任何列 表或集构成的集合均可以用这种方式引用,只有映射类除外(但也不是彻底排除在外,由于能够从映射得到一个列表。)因此说,把一个列表或集传递给方法的标准 途径是使用Collection类型的参数。

Vector 仍是ArrayList,哪个更好,为何?
要回答这个问题不能一律而论,有时候使用Vector比较好;有时是ArrayList,有时候这两个都不是最好的选择。你别期望可以得到一个简单确定答案,由于这要看你用它们干什么。下面有4个要考虑的因素:

(1)API

(2)同步处理

(3)数据增加性

(4)使用模式

下面针对这4个方面进行一一探讨

API
在由Ken Arnold等编著的《Java Programming Language》(Addison-Wesley, June 2000)一书中有这样的描述,Vector相似于ArrayList.。全部从API的角度来看这两个类很是类似。但他们之间也仍是有一些主要的区别 的。

同步性

Vector是同步的。这个类中的一些方法保证了Vector中的对象是线程安全的。而ArrayList则是异步的,所以ArrayList中的 对象并非线程安全的。由于同步的要求会影响执行的效率,因此若是你不须要线程安全的集合那么使用ArrayList是一个很好的选择,这样能够避免因为 同步带来的没必要要的性能开销。

数据增加

从内部实现机制来说ArrayList和Vector都是使用数组(Array)来控制集合中的对象。当你向这两种类型中增长元素的时候,若是元素 的数目超出了内部数组目前的长度它们都须要扩展内部数组的长度,Vector缺省状况下自动增加原来一倍的数组长度,ArrayList是原来的50%, 因此最后你得到的这个集合所占的空间老是比你实际须要的要大。因此若是你要在集合中保存大量的数据那么使用Vector有一些优点,由于你能够经过设置集 合的初始化大小来避免没必要要的资源开销。

使用模式

在ArrayList和Vector中,从一个指定的位置(经过索引)查找数据或是在集合的末尾增长、移除一个元素所花费的时间是同样的,这个时间 咱们用O(1)表示。可是,若是在集合的其余位置增长或移除元素那么花费的时间会呈线形增加:O(n-i),其中n表明集合中元素的个数,i表明元素增长 或移除元素的索引位置。为何会这样呢?觉得在进行上述操做的时候集合中第i和第i个元素以后的全部元素都要执行位移的操做。这一切意味着什么呢?
这意味着,你只是查找特定位置的元素或只在集合的末端增长、移除元素,那么使用Vector或ArrayList均可以。若是是其余操做,你最好选择其余的集合操做类。
比 如,LinkList集合类在增长或移除集合中任何位置的元素所花费的时间都是同样的—O(1),但它在索引一个元素的使用却比较慢-O(i),其中i是 索引的位置.使用ArrayList也很容易,由于你能够简单的使用索引来代替建立iterator对象的操做。LinkList也会为每一个插入的元素创 建对象,因此你要明白它也会带来额外的开销。

最后,在《Practical Java》一书中Peter Haggar建议使用一个简单的数组(Array)来代替Vector或ArrayList。尤为是对于执行效率要求高的程序更应如此。由于使用数组 (Array)避免了同步、额外的方法调用和没必要要的从新分配空间的操做。

相关文章
相关标签/搜索