集合框架之Collection接口

Collection 层次结构中的根接口。Collection表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接实现:它提供更具体的子接口(如 Set 和 List)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。

包 (bag) 或多集合(multiset)(可能包含重复元素的无序 collection)应该直接实现此接口。

所有通用的 Collection 实现类(通常通过它的一个子接口间接实现 Collection)应该提供两个“标准”构造方法:一个是 void(无参数)构造方法,用于创建空collection;另一个是带有 Collection 类型单参数的构造方法,用于创建一个具有与其参数相同元素新的 collection。实际上,后者允许用户复制任何 collection,以生成所需实现类型的一个等效 collection。尽管无法强制执行此约定(因为接口不能包含构造方法),但是 Java 平台库中所有通用的 Collection 实现都遵从它。

此接口中包含的“破坏性”方法,是指可修改其所操作的 collection 的那些方法,如果此 collection 不支持该操作,则指定这些方法抛出UnsupportedOperationException。如果是这样,那么在调用对该collection 无效时,这些方法可能,但并不一定抛出 UnsupportedOperationException。例如,如果要添加的 collection为空且不可修改,则对该 collection 调用 addAll(Collection) 方法时,可能但并不一定抛出异常。

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

由每个 collection 来确定其自身的同步策略。在没有实现的强烈保证的情况下,调用由另一进程正在更改的 collection 的方法可能会出现不确定行为;这包括直接调用,将 collection 传递给可能执行调用的方法,以及使用现有迭代器检查 collection。

CollectionsFramework 接口中的很多方法是根据 equals 方法定义的。例如,contains(Object o) 方法的规范声明:“当且仅当此 collection 包含至少一个满足 (o==null ? e==null :o.equals(e)) 的元素 e 时,返回 true。”不 应将此规范理解为它暗指调用具有非空参数 o的 Collection.contains 方法会导致为任意的 e 元素调用 o.equals(e) 方法。可随意对各种实现执行优化,只要避免调用 equals 即可,例如,通过首先比较两个元素的哈希码。(Object.hashCode() 规范保证哈希码不相等的两个对象不会相等)。较为常见的是,各种 Collections Framework 接口的实现可随意利用底层 Object 方法的指定行为,而不管实现程序认为它是否合适。

方法列表如下:

boolean add(Ee)

确保此 collection 包含指定的元素(可选操作)。

boolean addAll(Collection<?extends E> c)

将指定 collection 中的所有元素都添加到此collection 中(可选操作)。

void clear()

移除此 collection 中的所有元素(可选操作)。

boolean contains(Objecto)

如果此 collection 包含指定的元素,则返回true。

boolean containsAll(Collection<?>c)

如果此 collection 包含指定collection 中的所有元素,则返回 true。

boolean equals(Objecto)

比较此 collection 与指定对象是否相等。

int hashCode()

返回此 collection 的哈希码值。

boolean isEmpty()

如果此 collection 不包含元素,则返回true。

Iterator<E> iterator()

返回在此 collection 的元素上进行迭代的迭代器。

boolean remove(Objecto)

从此 collection 中移除指定元素的单个实例,如果存在的话(可选操作)。

boolean removeAll(Collection<?>c)

移除此 collection 中那些也包含在指定collection 中的所有元素(可选操作)。

boolean retainAll(Collection<?>c)

仅保留此 collection 中那些也包含在指定collection 的元素(可选操作)。

int size()

返回此 collection 中的元素数。

Object[] toArray()

返回包含此 collection 中所有元素的数组。

<T> T[] toArray(T[] a)

返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。

Collection接口包含了对集合执行基本操作的方法,如size(),isEmpty()等,还定义了一些批量操作的方法,比如containAll(),removeAll()等

需要注意的是,在一些不能包含重复值的Collection的子接口中(比如Set),使用add()方法添加元素时,如果该元素在集合中已经存在,并不会报错,而是返回false值,证明集合在该操作之后发生了变化

遍历集合有两种常用的方法,一个是使用for-each方法,一种是使用迭代器Iterator

下面结合代码实例来深入了解:

List <String> list = new ArrayList<String>();
         list.add("a");
         list.add("b");
         list.add("c");
         list.add("d");
         list.add("a");

         for(String str : list){
                System.out.println(str);
         }

         Set<String> set = new HashSet<String>(list);
         Iterator it = set.iterator();
         while(it.hasNext()){
                Stringstr = (String)it.next();
                System.out.println(str);
         }

List和Set均是Collection的子接口,而Collection接口继承了Iterable接口,继承了Iterable接口的类可以使用iterate()返回一个迭代器,for-each循环实际上就是使用iterate()方法返回的迭代器来对集合的元素进行迭代。除了Collection的子类,java中的数组也实现了Iterable接口,也可以使用for-each方法进行迭代

ArrayList我们使用for-each方法来遍历,而HashSet我们使用Iterator来遍历(当然反过来也是没问题的),需要注意的是,迭代器返回的是Object类型,需要进行类型转换,如果使用for-each迭代,在没有指定集合元素的类型下(Set s = new HashSet ()),程序会报错。

在构造HashSet的时候我们将list作为参数传入,但是由于Set接口不允许包含重复值,所以在set中实际上只会包含list中的前四个元素,第五个元素“a”是一个重复值,不会被再次插入到set中。Collection的子类都提供了两个构造方法,一种是无参的,构造一个空集合,一种是有参的,接受一个Collection,将之转换成符合自身规则的集合

在上面的例子中,我们使用List来引用集合而不是使用List接口的具体实现类,即

Set<String> set = new HashSet<String>(list)

而非

HashSet <String> set = new HashSet<String>(list)

这是一种良好的编程习惯,因为它赋予代码更强的弹性,假如我们现在想换成一个有序的集合,那么仅需要改变一下构造方法就行了

Set<String> set = new TreeSet<String>()

如果使用的是具体实现类引用,当我们替换一个集合容器时,可能还需要修改与之相关的一些列方法,这就违背了面向接口编程的原则

Collection的toArray()方法可以将一个集合转换成数组,数组存储的类型默认是Object类型,也可以使用泛型在运行时确定。数组的长度默认等于集合的元素总数

上一篇:android AIDL 语言用法


下一篇:KMP算法总♂结