Java Collections Framework

1.集合概述

Java中的集合,又叫容器。它是一个对象。用来存储并管理一组其他对象,存储在集合内的对象称为元素。简单地说,集合对象用来存储、检索、操作和统计一组元素。

在Java SE API中的java.util包设计了一组接口和类,用来实现以不同形式存放对象的存储结构。这样的设计结构被称为Java集合框架(JCF)。

集合框架中的主要接口和常用类层次图如下:


Java Collections Framework_第1张图片                                    


上述类图中,实线边框的是实现类,比如ArrayList,LinkedList,HashMap等,折线边框的是抽象类,比如AbstractCollection,AbstractList,AbstractMap等,而点线边框的是接口,比如Collection,Iterator,List等。


2.详解

2.1 Collection接口

Collection是使用泛型定义的接口,如果不想使用泛型方式操作的话,可以把泛型参数当作Object看待。另外,Java SE API并没有对Collection接口提供直接实现类,而是提供更具体的子接口实现类,以提供更具特点的对象存储结构。


2.2 Iterator接口

Collection接口中并没有声明直接获取集合中的某个元素的方法。Collection接口继承Iterable接口,Iterable接口提供的iterartor()方法会返回一个用于遍历集合内的所有元素迭代器。另外,Iterable接口提供还允许其子类的对象成为“for-each”语句的目标。

Iterator接口代表迭代器,可以对集合经行迭代。   


2.3 Set接口

Set接口继承自Collection接口,但它并没有在Collection接口的基础上增加新的方法。它代表的是不包含重复元素的集合。更准确地说,Set不包含满足e1.equals(e2)的元素。正如其名称所暗示的,此接口模仿了数学上的集合概念。

往Set集合存放对象时,它会自动调用对象的equals方法来比较是否与Set集合中的已有元素重复。因此,要存放到Set集合中的对象,在对应的类中就需要重写equals方法和hashCode方法来实现对象相等的规则。


2.4 HashSet实现类

HashSet类是Set接口的一个实现类,也是开发中用到的最多的一个Set。它的内部使用散列表来保存元素,所以HashSet也被称为散列集。HashSet在存放对象,首先会根据对象的哈希码值用固定的算法算出它的存储索引;然后把该对象存放到散列表的相应位置中。如果散列表没有其他元素,就直接存入;如果存在,就会将新对象跟该位置上原有的所有对象一一进行equals比较,还不存在就存放到当前位置其他元素的后面;如果存在,就无须再存放。所以,HashSet中不会包含重复的元素。

另外,使用迭代器迭代Set中存放的所有元素时,它将依次访问到所有的散列表元,而由于散列机制将各个元素分散在散列表的各个位置上,因此这些元素显然是以随机顺序访问的。说白了,HashSet并不保证元素存储时和取出时的顺序是一致。         

       

2.5 LinkedHashSet实现类

LinkedHashSet根据元素的哈希码进行存放,同时用链表记录元素的加入顺序,所以也被称为链式散裂集。由于LinkedHashSet会用链表来维护元素的加入顺序,增加维护链表的开支,它的运行速度会比HashSet稍慢。LinkedHashSet不允许重复元素,但会保存元素的存储顺序。


2.6 List接口

List接口继承了Collection接口,它是一个有序的集合,即会把保存的元素存入的顺序,所以也被称为序列。该接口在Collection提供的操作方法基础上添加面向位置的元素方法。


2.7 ArrayList实现类

ArrayList类是List接口中的典型实现。它采用可随需要而增长的动态数组结构来实现。标准数组是定长的,在数组创建之后,它们不能被加长或缩短。ArrayList是一个变长的对象数组,所以ArrayList被称为数组列表。当有存放的元素超出它的容量,它会自动增加容量;当对象删除后,数组也会自动缩小。ArrayList中使用索引来取出元素是最快的,因为它使用索引直接定位对象。但对ArrayList中的元素做删除或插入的速度很慢,因为它内部使用的是数组。


2.8 LinkedList 实现类

LinkedList是List接口的另一个常用实现类。它采用双链表结构来保存元素。在双向链表中的每个节点上,除了存放元素,还提供两个变量,用来存放下一个节点的引用和上一个节点的引用。LinkedList针对频繁的插入和删除元素的速度很高。但不适合快速地随机访问某个位置的元素。


2.9 Map接口

Java SE API 设计了Map接口来代表映射。该接口描述了从不重复的键到值的映射。Map接口定义了存储键/值对的方法,Map中不能有重复的键,Map实现类存储的映射都是通过键来唯一标识的。Map实现类的内部都是使用Set来存放映射对的“键”,所以存入Map中的映射对的“键”对应的类必须重写equals方法和hashcode方法。


2.10 HashMap实现类 

HashMap基于散列表的Map接口实现,它是实际开发使用最多的映射,它的内部对“键”采用Set进行散列存放,所以根据“键”去取“值”的效率很快。并且它允许使用null键和null值,但不保证映射对的存放顺序。


2.11 LinkedHashSet 实现类  

LinkedHashSet是HashSet的子类,它使用散列表存放键/值对,同时又使用双向链表根据键来保存映射对的加入顺序。


2.12 Vector实现类      

Vector也叫向量,它实现了List接口,内部也是使用动态数组来存储对象的,提供的元素方法几乎跟ArrayList一样,可以认为就是旧版的ArrayList类。与ArrayList不同的是,它提供了一个返回元素枚举对象的elements()方法,这个枚举接口也提供了类似Iterator接口的功能,能够迭代所以的元素。另外,它与ArrayList不同的,就是Vector是同步的(即线程安全的);而ArrayList是不同步的(即线程不安全的)。在无须考虑线程的情况下,使用ArrayList会有更高的运行效率。


2.13 Stack实现类

Stack实现类是Vector的子类,它是以后进先出(LIFO)方式存储元素的堆栈。Stack类中增加了5个方法对Vector进行拓展,分别为:

public E push (E item) 将元素压入堆栈顶部

public E pop() 移除堆栈顶部的对象,并作为此方法的值返回该对象

public E peek() 查看堆栈顶部的对象,但不从堆栈移除它

public boolean empty()  测试堆栈是否为空

public int search(Object o) 返回对象在堆栈的中位置,以1为基数


2.14 Hashtable 实现类

Hashtable类的功能与HashMap类似,它们都实现自相同的Map接口。只是Hashtable类的各个方法都是同步的。如果不需要同步,应该使用HashMap类。


2.15 Properties 实现类  

Properties类是Hashtable类的子类,也叫属性集。它是一个非常特殊的映射结构,主要有两个特殊特性:

1.键和值都是字符串。所以他不是泛型,不支持泛型操作。

2.属性集的键值对可以保存到一个文件,也可以从一个文件加载。

由于存储数据时不建议使用push()、putAll()和get()这类方法,而是使用setProperty(String key,String value)方法和getProperty(String key)方法。


2.16 Comparable接口              

java.lang.Comparable接口会强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序。该接口中声明了一个自然比较方法:int compareTo(T o)  

该方法比较此对象与指定对象的顺序。如果该对象小于指定对象,返回负整数;相等,返回零;如果该对象大于指定对象,返回整数。

要让自定义的类支持排序功能,就需要实现Comparable接口,并在compareTo方法中定义排序规则。


2.17 TreeSet实现类              

TreeSet类是Set系列用来支持元素自然排序的一个集合,它的内部采用“红黑树”来存储排序后的元素,所以也被称为树集。

每当把一个元素添加给树集,该元素将被纳入树状结构相应的排序位置。也就是说,TreeSet会按元素的自然排序来存放每个元素。当树集中的元素添加完毕,所有元素也就自然排序存放好了。


2.18 Comparator 接口                   

不过,使用Comparable接口来定义排序顺序有着明显的局限性,一个类只能实现该接口一次,即只能定义一个自然排序的规则。这时我们就需要让不同的排序集合使用不同的比较方法。具体的做法就是把一个实现了Comparator接口的类(排序器)的对象作为参数传递给该排序集合的构造方法,这个排序集合就会按照排序器指定的排序规则对元素经行排序存放。


2.19 TreeMap实现类

java集合框架中也提供了一个具备排序功能的映射类TreeMap,TreeMap类是根据其键的自然顺序对键值对进行排序的,当然也可以提供比较器(实现Comparator接口的类实例)对键值对进行排序。


3.集合工具类

3.1极值

   Collections类中提供以下方法求出指定集合中的极值:

  public static > T min(Collection coll  根据元素的自然排序,返回collection最小元素。

  public static > T max(Collection coll 根据元素的自然排序,返回collection最大元素。

  public static min(Collection coll,Comparator comp)  根据指定比较器产生的顺序,返回给定 collection 的最小元素。

  public static max(Collection coll,Comparator comp)  根据指定比较器产生的顺序,返回给定 collection 的最大元素。


3.2排序

  Collections类提供了两个方法对指定集合中的元素进行排序:

   public static > void sort(List list)  

   根据元素的自然顺序 对指定列表按升序进行排序。列表中的所有元素都必须实现 Comparable 接口。


   public static void sort(List list,Comparator c)   

   根据指定比较器产生的顺序对指定列表进行排序。


3.3混排

  Collections类中还提供了以下两个方法对指定的List集合中元素进行混排。


  public static void shuffle(List list)    使用默认随机源对指定列表进行置换。     


  public static void shuffle(List list,Random rnd)    使用指定的随机源对指定列表进行置换。


3.4查找

   Collections类中也提供了以下两个方法对指定的集合中元素中查找指定的元素。


   public static intbinarySearch(List list, T key,Comparator c)  

   使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据指定的比较器对列表进行升序排序


    public static intbinarySearch(List> list,T key)  

    使用二分搜索法搜索指定列表,以获得指定对象。在进行此调用之前,必须根据列表元素的自然顺序对列表进行升序排序


3.5同步

  HashSet、LinkedHashSet、ArrayList、LinkedList、HashMap、LinkedHashMap、TreeSet和TreeMap都是不同步的,即线程不安全的。如果多个线程操作这些集合类的一个实例,就可能出现一些错误情况。


  public static Collection synchronizedCollection(Collection c)    

  public static Set synchronizedSet(Set s)             

  public static SortedSet synchronizedSortedSet(SortedSet s)             

  public static List synchronizedList(List list)                 

  public static Map synchronizedMap(Map m)               

  public static SortedMap synchronizedSortedMap(SortedMap m)             


这些方法都是可以将指定将指定的参数的集合对象转换成支持同步的同步类型对象。

但需要注意的一点:必须手工在返回的集合类对象上进行同步(即添加synchronized关键字


4.如何选择合适的集合类

4.1如果数据存放对顺序没有要求,首选HashSet。

4.2如数据存放有顺序要求,首选ArrayList。

4.3如果数据存放对顺序有要求,且需要频繁地增删元素,首选LinkedList。

4.4如果数据需要以“键-值”对存放,首选HashMap。

4.5如果数据需要按指定的自然顺序排序,就用TreeSet或TreeMap。


5.效率方面

5.1以Hash开头的集合类,元素的读取和修改的效率都是最高的。

5.2以Array开头的集合类,元素的读取快,但修改慢。

5.3以Linked开头的集合类,元素的读取慢,但修改快。


你可能感兴趣的:(Java,语言)