java.util.Collection
是集合结构的根接口,定义了所有集合类型都应该提供的基础方法。在java中,集合的概念与数学中的集合概念相同:代表一个对象的分组,包含的每个对象称为集合的元素。每个集合可以指定是否允许重复元素,也可以指定其是否是有序的;在Sun JDK中并没有提供这个接口的直接实现,而是将其划分为更加特定的接口去实现;
所有常规意义上的集合实现类应当提供两个“标准”集合构造方法:返回一个空集合的无参构造函数;根据一个集合生成一个拥有相同元素的集合构造方法。第二种构造方法允许用户复制任意集合中的所有元素到一个特定集合中;虽然没有强制指定所有所有的集合类都应当提供这两种构造方法,但是在java中,仍然强烈建议用户提供这两个构造方法。
如果集合接口中指定的方法对于正在实现的集合并不适用,则在不使用的方法中应当抛出UnsupportedOperationException
来提醒集合的使用用户。
某些集合对鱼其中包含的元素有严格的限制。例如:某些集合不允许null
元素,某些集合要求包含的元素为特定的类型;当试图添加一个不支持的元素到集合中时,将抛出非检查异常,通常为:NullPointerException
或者ClassCastException
等。当从集合中查找一个非法类型的元素,其可能抛出一个异常或者简单的返回false
;一般来说,不同的集合实现会对将非法元素插入到集合的操作选取两种策略:直接抛出异常、忽略这次操作,正常执行;在这种情况下,抛出的异常类型对于实现来说是可选的;
不同的集合实现需要指定自己的同步策略。对于缺少强同步策略的实现而言,调用正在被其他线程改变的集合方法都可能导致不可预期的结果,调用方法包括:直接调用、将集合作为参数传递至一个可能调用集合方法的方法中、使用一个已经存在的集合迭代器进行集合的操作等。
集合框架接口中的许多方法均基于equals
实现。例如:contains(Object o)
等。当然,我们也可以自己实现集合中的方法,从而避免对于equals()
方法的依赖;但是一般来说,在实现集合接口的相关方法时,仍然建议使用Object
提供的默认实现。
int size()
计算当前集合中的元素个数,当集合中的元素个数大于Integer.MAX_VALUE
时,则返回Integer.MAX_VALUE
。是不是说明一个集合中的元素个数最多为Integer.MAX_VALUE
呢?在完成集合框架的学习后,反过头来回答,做个备注;
boolean isEmpty()
当一个集合中不包含任何元素时,返回true
,其它时候返回false
boolean contains(Object o)
判断集合中是否包含一个特定的元素时,包含返回true
。在正式的实现中,一般判定的条件为当集合中至少包含一个满足条件(o==null ? e==null : o.equals(e))
的元素。】
可能选择抛出两种异常:
o
于集合中的类型不匹配时,可以选择抛出:ClassCastException
;o
为null
,而集合中不允许存在null
时,则可以选择抛出:NullPointerException
;Iterator iterator()
返回一个可以迭代本集合中元素的迭代器。迭代器不保证返回元素的顺序与集合中元素的顺序相同,但是可以在特定的实现中来保证顺序性。
Object[] toArray()
返回一个包含集合中所有元素的数组。数组中的元素顺序必须与调用这个方法时集合迭代器返回元素的顺序相同。这个方法必须申请一个新的数组,即使这个集合的实现是以数组为基础实现的(即:集合中并没有保持一个对于这个需要返回的数组的引用)。因此调用者可以随意更改返回数组的信息,而不用担心影响原集合中的元素;
这个方法是连接基于集合实现的API与基于数组实现的API之间的桥梁;
T[] toArray(T[] a)
返回一个包含集合中所有元素的数组;返回数组的类型由参数中传入的数组的类型决定。当传入的数组可以容纳集合中的所有元素时,则会直接将传入的数组引用返回。否则,将根据传入数组的类型和集合大小申请一个新的数组,在完成复制后,将新数组返回;
当数组中的容量足以容纳集合中的所有元素是,完成复制后,集合元素在数组中的对应的位置的下一个位置将会设为null
。这在调用者确认集合中不含有任何null
元素时,可以用于确认集合的大小。
数组中的元素顺序必须与调用这个方法时集合迭代器返回元素的顺序相同。出了完成于上述toArray()
方法类似的功能为,其允许指定输出数组的类型,而在某些特定情况下,可以用于节省申请空间时的开销;
可能抛出的异常:
ArrayStoreException
;null
时,则抛出:NullPointerException
;boolean add(E e);
如果集合因为调用这个方法发生了改变,则返回true
,否则返回false
。如果集合中不允许重复元素,则需要首先检测需要添加的元素在集合中是否存在。
实现该方法的集合应当对可以放入集合中的元素进行限制。例如:某些集合不允许添加null
元素,有些集合会对可以加入集合的类型进行强校验。所有实现集合接口的类应当在文档中说明可以添加的元素的限制条件。
如果一个集合因除了已经包含该元素意外的原因拒绝添加一个元素,则应当抛出一个异常指明原因,而不是简单的返回false
;
可能抛出的异常包括:
UnsupportedOperationException
:该集合不支持添加元素操作;ClassCastException
:集合拒绝添加某种类型的元素;NullPointerException
:需要添加的元素为null
,但是集合不允许包含null
元素;IllegalArgumentException
:需要添加元素的某些属性导致集合拒绝添加操作;IllegalStateException
:由于集合插入限制条件导致的元素不能添加;boolean remove(Object o)
从集合中删除单个元素,但这是一个可选的方法。当集合中包含满足条件(o==null ? e==null : o.equals(e)
的元素时,则将其删除。如果集合因为这个方法发生改变,则返回true
。
可能抛出的异常为:
ClassCastException
:需要删除的元素类型与集合中的元素类型不匹配;(可选)NullPointerException
:需要删除的元素为null
,而集合不允许null
存在;(可选)UnsupportedOperationException
:集合不支持删除操作;boolean containsAll(Collection c)
判断集合中是否包含集合c
中的所有元素。如果包含所有元素,返回true
。
可能抛出异常:
ClassCastException
:如果c
中存在元素与集合中的元素类型不匹配;NullPointerException
:如果c
中包含null
元素,而检测集合中不允许存在null
;或者c
为null
;boolean addAll(Collection c)
将集合c
中所有的元素添加到指定集合中(可选)。当本方法执行的过程中,集合c
中发生了改变,则方法的执行结果不可控。
可能抛出的异常为:
UnsupportedOperationException
:集合实现不支持本操作;ClassCastException
:如果c
中存在元素与集合中的元素类型不匹配;NullPointerException
:如果c
中包含null
元素,而检测集合中不允许存在null
;或者c
为null
;IllegalArgumentException
:c
中元素的某些属性导致集合拒绝添加操作;IllegalStateException
:由于集合插入限制条件导致的c
中的某些元素不能添加;boolean removeAll(Collection> c)
删除集合c
中的所有元素;异常信息与判定条件参照:boolean remove(Object o)
与boolean contains(Object o)
boolean retainAll(Collection c);
删除集合中除c
中包含的元素以外的元素。抛出的异常信息与判定条件参照:boolean remove(Object o)
与boolean contains(Object o)
。
void clear();
删除集合中包含的所有元素。
boolean equals(Object o)
判断对象c
与集合是否相等。
由于集合接口没有添加任何额外操作到方法Object.equals
,在直接实现集合接口(即:创建了一个新的集合类,但不是一个Set,也不是一个List)的类需要谨慎选择是否需要重写equals()
方法。一般没必要进行重写操作,最简单的方法就是依赖Object.equals
判定是否相等,除非在某些情况下,我们需要实现”值等”(在List与Set中均有实现),而不是简单判断是否引用同一个对象。
一般对于Object.equals
要求有对称性,即:当且仅当b.equals(a)
时有a.equals(b)
。而List和Set实现的equals
方法的目的是判定列表与列表相等,set与set相等。因此对于一个非基于List
和Set
的集合实现,调用equals
函数与其它list
或者set
比较时,都会返回false;
int hashCode()
返回集合的哈希码。由于集合接口没有添加任何额外操作到方法Object.hashCode
,在重写Object.equals
时都必须注意:必须重写Object.hashCode
函数,以保证Object.hashCode
的常规要求,即:当c1.equals(c2)
时,c1.hashCode()==c2.hashCode()
。