java集合类

来源:互联网 发布:mac php开发环境 编辑:程序博客网 时间:2024/06/10 15:54

Collection接口
  Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements)。
Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的“子接口”如List和Set。
  所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Collection,有一个 Collection参数的构造函数用于创建一个新的Collection,这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection。
  如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,使用该迭代子即可逐一访问Collection中每一个元素。典型的用法如下:
    Iterator it = collection.iterator(); // 获得一个迭代子
    while(it.hasNext()) {
      Object obj = it.next(); // 得到下一个元素
    }
  由Collection接口派生的两个接口是List和Set。

让我们转到对框架实现的研究,具体的集合类遵循命名约定,并将基本数据结构和框架接口相结合。除了四个历史集合类外,Java 2 框架还引入了六个集合实现,如下表所示。关于历史集合类如何转换、比如说,如何修改Hashtable 并结合到框架中,请参阅历史集合类 。

接口实现历史集合类SetHashSetTreeSetListArrayListVectorLinkedListStackMapHashMapHashtableTreeMapProperties

这里没有 Collection 接口的实现。历史集合类,之所以这样命名是因为从 Java 类库 1.0 发行版就开始沿用至今了。

如果从历史集合类转换到新的框架类,主要差异之一在于所有的操作都和新类不同步。您可以往新类中添加同步的实现,但您不能把它从旧的类中除去。

Collection collection = new ArrayList();(这样写的好处在于,以后如果要理性不同的集合,可以省略很多麻烦。因为都是用Collection接口里的方法,)

 booleanadd(E o)
          确保此 collection 包含指定的元素(可选操作)。
 booleanaddAll(Collection<? extends E> c)
          将指定 collection 中的所有元素都添加到此 collection 中(可选操作)。
 voidclear()
          移除此 collection 中的所有元素(可选操作)。
 booleancontains(Object o)
          如果此 collection 包含指定的元素,则返回 true
 booleancontainsAll(Collection<?> c)
          如果此 collection 包含指定 collection 中的所有元素,则返回true
 booleanequals(Object o)
          比较此 collection 与指定对象是否相等。
 inthashCode()
          返回此 collection 的哈希码值。
 booleanisEmpty()
          如果此 collection 不包含元素,则返回 true
 Iterator<E>iterator()
          返回在此 collection 的元素上进行迭代的迭代器。
 booleanremove(Object o)
          从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。
 booleanremoveAll(Collection<?> c)
          移除此 collection 中那些也包含在指定 collection 中的所有元素(可选操作)。
 booleanretainAll(Collection<?> c)
          仅保留此 collection 中那些也包含在指定 collection 的元素(可选操作)。
 intsize()
          返回此 collection 中的元素数。
 Object[]toArray()
          返回包含此 collection 中所有元素的数组。
<T> T[]toArray(T[] a)
          返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。

*All方法参数的类型都为Collection ,大多数方法都是返回boolean类型值,Collection 接口用于表示任何对象或元素组。想要尽可能以常规方式处理一组元素时,就使用这一接口。(如,可以直接add(100),可以是普通数据类型)。

容器类对象在调用remove,contains等方法时需要比较对象是否相等地,这会涉及到对象类型的equals方法和hashcode方法。即,相等的对象应该有相等的hashcode.当然,如果是自定义的类型,需要重写这两个方法。

iterator接口

 booleanhasNext()
          如果仍有元素可以迭代,则返回 true
 Enext()
          返回迭代的下一个元素。
 voidremove()
          从迭代器指向的集合中移除迭代器返回的最后一个元素(可选操作)。
Set
Set接口同样是Collection接口的一个子接口,它表示数学意义上的集合概念。Set中不包含重复的元素,即Set中不存两个这样的元素e1e2,使得e1.equals(e2)true。由于Set接口提供的数据结构是数学意义上集合概念的抽象,因此它需要支持对象的添加、删除,而不需提供随机访问。故Set接口与Collection的接口相同,在此对里面的方法不作介绍。 booleanadd(E o)
          如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。
 booleanaddAll(Collection<? extends E> c)
          如果 set 中没有指定 collection 中的所有元素,则将其添加到此 set 中(可选操作)。
 voidclear()
          移除 set 中的所有元素(可选操作)。
 booleancontains(Object o)
          如果 set 包含指定的元素,则返回 true
 booleancontainsAll(Collection<?> c)
          如果此 set 包含指定 collection 的所有元素,则返回 true
 booleanequals(Object o)
          比较指定对象与此 set 的相等性。
 inthashCode()
          返回 set 的哈希码值。
 booleanisEmpty()
          如果 set 不包含元素,则返回 true
 Iterator<E>iterator()
          返回在此 set 中的元素上进行迭代的迭代器。
 booleanremove(Object o)
          如果 set 中存在指定的元素,则将其移除(可选操作)。
 booleanremoveAll(Collection<?> c)
          移除 set 中那些包含在指定 collection 中的元素(可选操作)。
 booleanretainAll(Collection<?> c)
          仅保留 set 中那些包含在指定 collection 中的元素(可选操作)。
 intsize()
          返回 set 中的元素数(其容量)。
 Object[]toArray()
          返回一个包含 set 中所有元素的数组。
<T> T[]toArray(T[] a)
          返回一个包含 set 中所有元素的数组;返回数组的运行时类型是指定数组的类型。

按照定义,Set 接口继承 Collection 接口,而且它不允许集合中存在重复项。所有原始方法都是现成的,没有引入新方法。具体的Set 实现类依赖添加的对象的 equals()方法来检查等同性。

HashSet 类和 TreeSet 类

“集合框架”支持 Set 接口两种普通的实现:HashSet 和TreeSet。在更多情况下,您会使用 HashSet 存储重复自由的集合。考虑到效率,添加到 HashSet 的对象需要采用恰当分配散列码的方式来实现hashCode() 方法。虽然大多数系统类覆盖了 Object 中缺省的hashCode()实现,但创建您自己的要添加到 HashSet 的类时,别忘了覆盖 hashCode()。当您要从集合中以有序的方式抽取元素时,TreeSet 实现会有用处。为了能顺利进行,添加到TreeSet 的元素必须是可排序的。 “集合框架”添加对 Comparable 元素的支持,在排序的“可比较的接口”部分中会详细介绍。我们暂且假定一棵树知道如何保持java.lang 包装程序器类元素的有序状态。一般说来,先把元素添加到 HashSet,再把集合转换为TreeSet 来进行有序遍历会更快。

为优化 HashSet 空间的使用,您可以调优初始容量和负载因子。TreeSet 不包含调优选项,因为树总是平衡的,保证了插入、删除、查询的性能为log(n)

HashSet 和 TreeSet 都实现 Cloneable 接口。

集的使用示例

为演示具体 Set 类的使用,下面的程序创建了一个 HashSet,并往里添加了一组名字,其中有个名字添加了两次。接着,程序把集中名字的列表打印出来,演示了重复的名字没有出现。接着,程序把集作为TreeSet 来处理,并显示有序的列表。

import java.util.*;public class SetExample {  public static void main(String args[]) {    Set set = new HashSet();    set.add("Bernadine");    set.add("Elizabeth");    set.add("Gene");    set.add("Elizabeth");    set.add("Clara");    System.out.println(set);    Set sortedSet = new TreeSet(set);    System.out.println(sortedSet);  }}

运行程序产生了以下输出。请注意重复的条目只出现了一次,列表的第二次输出已按字母顺序排序。

[Gene, Clara, Bernadine, Elizabeth][Bernadine, Clara, Elizabeth, Gene]

List 接口

List 接口继承了 Collection 接口以定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理,还添加了面向位置的操作。

有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。

与 set 不同,列表通常允许重复的元素。更正式地说,列表通常允许满足 e1.equals(e2) 的元素对 e1e2,并且如果列表本身允许 null 元素的话,通常它们允许多个 null 元素。难免有人希望通过在用户尝试插入重复元素时抛出运行时异常的方法来禁止重复的列表,但我们希望这种用法越少越好。

List 接口在 iteratoraddremoveequalshashCode 方法的协定上加了一些其他约定,超过了 Collection 接口中指定的约定。为方便起见,这里也包括了其他继承方法的声明。

List 接口提供了 4 种对列表元素进行定位(索引)访问方法。列表(像 Java 数组一样)是基于 0 的。注意,这些操作可能在和某些实现(例如 LinkedList 类)的索引值成比例的时间内执行。因此,如果调用方不知道实现,那么在列表元素上迭代通常优于用索引遍历列表。

List 接口提供了特殊的迭代器,称为 ListIterator,除了允许 Iterator 接口提供的正常操作外,该迭代器还允许元素插入和替换,以及双向访问。还提供了一个方法来获取从列表中指定位置开始的列表迭代器。

List 接口提供了两种搜索指定对象的方法。从性能的观点来看,应该小心使用这些方法。在很多实现中,它们将执行高开销的线性搜索。

List 接口提供了两种在列表的任意位置高效插入和移除多个元素的方法。

注意:尽管列表允许把自身作为元素包含在内,但建议要特别小心:在这样的列表上,equalshashCode 方法不再是定义良好的。

某些列表实现对列表可能包含的元素有限制。例如,某些实现禁止 null 元素,而某些实现则对元素的类型有限制。试图添加不合格的元素会抛出未经检查的异常,通常是 NullPointerExceptionClassCastException。试图查询不合格的元素是否存在可能会抛出异常,也可能简单地返回 false;某些实现会采用前一种行为,而某些则采用后者。概括地说,试图对不合格元素执行操作时,如果完成该操作后不会导致在列表中插入不合格的元素,则该操作可能抛出一个异常,也可能成功,这取决于实现的选择。此接口的规范中将这样的异常标记为“可选”。

面向位置的操作包括插入某个元素或 Collection 的功能,还包括获取、除去或更改元素的功能。在 List 中搜索元素可以从列表的头部或尾部开始,如果找到元素,还将报告元素所在的位置。

  • void add(int index, Object element)
  • boolean addAll(int index, Collection collection)
  • Object get(int index)
  • int indexOf(Object element)
  • int lastIndexOf(Object element)
  • Object remove(int index)
  • Object set(int index, Object element)

List 接口不但以位置友好的方式遍历整个列表,还能处理集合的子集:

  • ListIterator listIterator()
  • ListIterator listIterator(int startIndex)
  • List subList(int fromIndex, int toIndex)

处理 subList() 时,位于 fromIndex 的元素在子列表中,而位于 toIndex 的元素则不是,提醒这一点很重要。以下 for-loop 测试案例大致反映了这一点:

for (int i=fromIndex; i<toIndex; i++) {  // process element at position i}

此外,我们还应该提醒的是 ― 对子列表的更改(如 add()remove()set() 调用)对底层 List 也有影响。

 booleanadd(E o)
          向列表的尾部追加指定的元素(可选操作)。
 voidadd(int index, E element)
          在列表的指定位置插入指定元素(可选操作)。
 booleanaddAll(Collection<? extends E> c)
          追加指定 collection 中的所有元素到此列表的结尾,顺序是指定 collection 的迭代器返回这些元素的顺序(可选操作)。
 booleanaddAll(int index, Collection<? extends E> c)
          将指定 collection 中的所有元素都插入到列表中的指定位置(可选操作)。
 voidclear()
          从列表中移除所有元素(可选操作)。
 booleancontains(Object o)
          如果列表包含指定的元素,则返回 true
 booleancontainsAll(Collection<?> c)
          如果列表包含指定 collection 的所有元素,则返回 true
 booleanequals(Object o)
          比较指定的对象与列表是否相等。
 Eget(int index)
          返回列表中指定位置的元素。
 inthashCode()
          返回列表的哈希码值。
 intindexOf(Object o)
          返回列表中首次出现指定元素的索引,如果列表不包含此元素,则返回 -1。
 booleanisEmpty()
          如果列表不包含元素,则返回 true
 Iterator<E>iterator()
          返回以正确顺序在列表的元素上进行迭代的迭代器。
 intlastIndexOf(Object o)
          返回列表中最后出现指定元素的索引,如果列表不包含此元素,则返回 -1。
 ListIterator<E>listIterator()
          返回列表中元素的列表迭代器(以正确的顺序)。
 ListIterator<E>listIterator(int index)
          返回列表中元素的列表迭代器(以正确的顺序),从列表的指定位置开始。
 Eremove(int index)
          移除列表中指定位置的元素(可选操作)。
 booleanremove(Object o)
          移除列表中出现的首个指定元素(可选操作)。
 booleanremoveAll(Collection<?> c)
          从列表中移除指定 collection 中包含的所有元素(可选操作)。
 booleanretainAll(Collection<?> c)
          仅在列表中保留指定 collection 中所包含的元素(可选操作)。
 Eset(int index, E element)
          用指定元素替换列表中指定位置的元素(可选操作)。
 intsize()
          返回列表中的元素数。
 List<E>subList(int fromIndex, int toIndex)
          返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图。
 Object[]toArray()
          返回以正确顺序包含列表中的所有元素的数组。
<T> T[]toArray(T[] a)
          返回以正确顺序包含列表中所有元素的数组;返回数组的运行时类型是指定数组的运行时类型。

其中set方法返回的是被替换的内容。

 

Linked 改快读慢

Array 读快改慢

Hash 两都之间

Collection是集合接口
    |————Set子接口:无序,不允许重复。
    |————List子接口:有序,可以有重复元素。

    区别:Collections是集合类

    Set和List对比:
    Set:检索元素效率低下,删除和插入效率高,插入和删除不会引起元素位置改变。
    List:和数组类似,List可以动态增长,查找元素效率高,插入删除元素效率低,因为会引起其他元素位置改变。

    Set和List具体子类:
    Set
     |————HashSet:以哈希表的形式存放元素,插入删除速度很快。

    List
     |————ArrayList:动态数组
     |————LinkedList:链表、队列、堆栈。

    Array和java.util.Vector
    Vector是一种老的动态数组,是线程同步的,效率很低,一般不赞成使用。

 

Map 接口

Map 接口不是 Collection 接口的继承。而是从自己的用于维护键-值关联的接口层次结构入手。按定义,该接口描述了从不重复的键到值的映射。

我们可以把这个接口方法分成三组操作:改变、查询和提供可选视图。

改变操作允许您从映射中添加和除去键-值对。键和值都可以为 null。但是,您不能把Map 作为一个键或值添加给自身。

  • Object put(Object key, Object value)返回值是被替换的值。
  • Object remove(Object key)
  • void putAll(Map mapping)
  • void clear()

查询操作允许您检查映射内容:

  • Object get(Object key)
  • boolean containsKey(Object key)
  • boolean containsValue(Object value)
  • int size()
  • boolean isEmpty()

最后一组方法允许您把键或值的组作为集合来处理。

  • public Set keySet()
  • public Collection values()
  • public Set entrySet()

因为映射中键的集合必须是唯一的,您用 Set 支持。因为映射中值的集合可能不唯一,您用Collection 支持。最后一个方法返回一个实现 Map.Entry 接口的元素 Set

Map.Entry 接口

Map 的 entrySet() 方法返回一个实现Map.Entry 接口的对象集合。集合中每个对象都是底层 Map 中一个特定的键-值对。

通过这个集合迭代,您可以获得每一条目的键或值并对值进行更改。但是,如果底层 Map 在Map.Entry 接口的setValue() 方法外部被修改,此条目集就会变得无效,并导致迭代器行为未定义。

HashMap 类和 TreeMap 类

“集合框架”提供两种常规的 Map 实现:HashMap 和TreeMap。和所有的具体实现一样,使用哪种实现取决于您的特定需要。在Map 中插入、删除和定位元素,HashMap 是最好的选择。但如果您要按顺序遍历键,那么TreeMap 会更好。根据集合大小,先把元素添加到 HashMap,再把这种映射转换成一个用于有序键遍历的 TreeMap 可能更快。使用HashMap 要求添加的键类明确定义了 hashCode() 实现。有了TreeMap 实现,添加到映射的元素一定是可排序的。我们将在排序中详细介绍。

为了优化 HashMap 空间的使用,您可以调优初始容量和负载因子。这个TreeMap 没有调优选项,因为该树总处于平衡状态。

HashMap 和 TreeMap 都实现Cloneable 接口。

Hashtable 类和 Properties 类是Map 接口的历史实现。我们将在Dictionary 类、Hashtable 类和 Properties 类中讨论。

映射的使用示例

以下程序演示了具体 Map 类的使用。该程序对自命令行传递的词进行频率计数。HashMap 起初用于数据存储。后来,映射被转换为TreeMap 以显示有序的键列列表。

import java.util.*;public class MapExample {  public static void main(String args[]) {    Map map = new HashMap();    Integer ONE = new Integer(1);    for (int i=0, n=args.length; i<n; i++) {      String key = args[i];      Integer frequency = (Integer)map.get(key);      if (frequency == null) {        frequency = ONE;      } else {        int value = frequency.intValue();        frequency = new Integer(value + 1);      }      map.put(key, frequency);    }    System.out.println(map);    Map sortedMap = new TreeMap(map);    System.out.println(sortedMap);  }}

用 Bill of Rights 的第三篇文章的文本运行程序产生下列输出,请注意有序输出看起来多么有用!

无序输出:

{prescribed=1, a=1, time=2, any=1, no=1, shall=1, nor=1, peace=1, owner=1, soldier=1, to=1, the=2, law=1, but=1, manner=1, without=1, house=1, in=4, by=1, consent=1, war=1, quartered=1, be=2, of=3}

有序输出:

{a=1, any=1, be=2, but=1, by=1, consent=1, house=1, in=4, law=1, manner=1, no=1, nor=1, of=3, owner=1, peace=1, prescribed=1, quartered=1, shall=1, soldier=1, the=2, time=2, to=1, war=1, without=1}

 

原创粉丝点击