Java Collection FrameworkCollection 接口文档格式.docx
《Java Collection FrameworkCollection 接口文档格式.docx》由会员分享,可在线阅读,更多相关《Java Collection FrameworkCollection 接口文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
Collection接口的定义如下:
publicinterfaceCollection<
E>
extendsIterable<
{...}
2、行为
java.util.Collection接口是描述Set和List集合类型的根接口,下面给出了Collection的所有行为(不包括从Object继承而来的方法),因此它们也刻画了Set或List执行的所有行为(List还有额外的功能)。
Collection的行为分类和详细列表如下:
注意到,其中不包含随机访问所选择的元素get()方法,因为Collection包含Set,而Set是自己维护顺序的。
因此,若想访问、遍历Collection中的元素,则必须使用迭代器;
另外,这些方法的默认实现(AbstractCollection)均直接或间接使用了迭代器。
三、Collection接口的默认实现:
1、JDK对AbstractCollection抽象类的描述
此抽象类提供Collection接口的骨干实现,以最大限度地减少实现此接口所需的工作。
要实现一个不可修改的collection,编程人员只需扩展此类,并提供iterator和size方法的实现。
(iterator方法返回的迭代器必须实现hasNext和next。
);
要实现可修改的collection,编程人员必须另外重写此类的add方法(否则,会抛出UnsupportedOperationException),iterator方法返回的迭代器还必须另外实现其remove方法(AbstractCollection的移除方法间接调用迭代器的移除方法)。
按照Collection接口规范中的建议,编程人员通常应提供一个void(无参数)和Collection构造方法。
AbstractCollection抽象类定义如下:
publicabstractclassAbstractCollection<
implementsCollection<
2、行为(对上述Collection接口中方法的实现情况)
下面给出了抽象类AbstractCollection对Collection接口的实现情况:
publicbooleanadd(Ee){
thrownewUnsupportedOperationException();
}
publicbooleanaddAll(Collection<
?
extendsE>
c){
booleanmodified=false;
Iterator<
e=c.iterator();
while(e.hasNext()){
if(add(e.next()))//调用了上面定义的add方法
modified=true;
returnmodified;
publicabstractIterator<
iterator();
//未提供具体实现,将实现延迟到具体容器
publicbooleanremove(Objecto){
e=iterator();
if(o==null){
if(e.next()==null){
e.remove();
//内部使用了迭代器的remove方法,故具体容器的迭代器实现密切相关
returntrue;
}else{
if(o.equals(e.next())){
returnfalse;
publicbooleanremoveAll(Collection<
>
if(c.contains(e.next())){
publicbooleanretainAll(Collection<
if(!
c.contains(e.next())){
publicvoidclear(){
e.next();
publicbooleancontains(Objecto){
while(e.hasNext())
if(e.next()==null)
if(o.equals(e.next()))//内部调用了的equals方法,故与equals方法实现密切相关
publicbooleancontainsAll(Collection<
contains(e.next()))//内部调用了的contains方法,故与contains方法实现密切相关
//此处省略两个toArray方法的实现
publicabstractintsize();
publicbooleanisEmpty(){
returnsize()==0;
//内部调用了的size方法,故与size方法实现密切相关
}
对以上实现进行总结:
【增】:
add,addAll两个方法的实现是可选的,此处均默认UnsupportedOperationException;
【查】:
iterator未提供具体实现,将实现延迟到具体容器,其对外屏蔽了不同容器的差异性,以统一的方式对容器访问、遍历;
【删】:
remove(Object),removeAll(Collection<
),retainAll(Collection<
)和clear()四个方法的实现均直接调用了具体容器的迭代器(由iterator()方法返回)的remove方法;
contains(Objecto)和containsAll(Collection<
c)两个方法的实现均直接或间接调用了元素的equals方法;
【基本方法】:
size方法实现与具体容器相关,isEmpty方法的实现均直接调用了size方法;
【容器与数组转换】:
分别提供与泛型toArray方法和原生toArray方法;
从源代码中我们可以知道,几乎所有方法的实现都与迭代器相关,并且有以下特点:
执行各种不同的添加和移除方法在Collection接口中都是可选操作,因为他们会改变容器的结构;
Collection接口中的读取方法都不是可选操作;
四、Optionaloperations(可选操作)
1、简述
执行各种不同的添加和移除方法在Collection接口中都是可选操作,这意味着实现类并不需要为这些方法提供功能定义。
这是一种很不寻常的接口定义方式。
正如你所看到的那样,接口是面向对象设计中的契约,它声明“无论你选择如何实现该接口,我保证你可以向该接口发送这些消息。
”但可选操作违反这个非常基本的原则,它声明调用某些方法将不会执行有意义的行为,相反,他们会抛出异常。
为什么会将方法定义为可选呢?
因为这样做可以防止在设计中出现接口爆炸的情形。
容器类库中的设计看起来总是为了描述每个主题的变体,而最终患上了令人困惑的接口过剩症。
甚至这么做仍不能捕获接口的各种特例,因为总是有人会发明新的接口。
“未获支持的操作”这种方式可以实现Java容器类库的一个重要目标:
容器应易学易用。
未获支持的操作是一种特例,可以延迟到需要时实现。
但是,为了让这种方式能够工作:
UnsupportedOperationException必须是一种罕见事件。
即,对于大多数类而言,所有操作都应该可以工作,只有在特例(例如,通过Arrays.asList()所得到的容器)中才会有未获支持的操作。
在Java容器类库中确实如此,因为你在99%的时间里使用的容器类,如ArrayList、LinkedList、HashSet和HashMap,以及其他的具体实现,都支持所有操作。
这种设计留下了一个“后门”,如果你想创建新的Collection,但是没有为Collection接口中的所有方法都提供有意义的定义,那么它仍旧适合现有类库。
如果一个操作是未获支持的,那么在实现接口的时候可能就会导致UnsupportedOperationException异常,而不是将产品程序交给客户后才出现此异常,这种情况是有道理的。
毕竟,他表示编程上有错误:
使用了不正确的接口实现。
值得注意的是,未获支持操作只有在运行时才能探测到,因此他们表示动态类型检查。
2、示例
最常见的未获支持的操作,都来源于背后由固定尺寸的数据结构支持的容器。
当你用Arrays.asList()将数组转换为List时,就会得到这样的容器。
此外,你还可以通过使用Collection类中“不可修改”的方法,选择创建任何会抛出会抛出UnsupportedOperationException的容器。
请看下面的例子:
publicclassUnsupported{
staticvoidtest(Stringmsg,List<
String>
list){
System.out.println("
---"
+msg+"
---"
Collection<
c=list;
subList=list.subList(1,8);
//Copyofthesublist:
c2=newArrayList<
(subList);
try{
c.retainAll(c2);
}catch(Exceptione){
retainAll():
"
+e);
c.removeAll(c2);
removeAll():
c.clear();
clear():
c.add("
X"
add():
c.addAll(c2);
addAll():
c.remove("
C"
remove():
//TheList.set()methodmodifiesthevaluebut
//doesn’tchangethesizeofthedatastructure:
list.set(0,"
List.set():
publicstaticvoidmain(String[]args){
List<
list=Arrays.asList("
ABCDEFGHIJKL"
.split("
));
test("
ModifiableCopy"
newArrayList<
(list));
//产生新的尺寸可调的
//ArrayList
Arrays.asList()"
list);
//产生固定尺寸的ArrayList
unmodifiableList()"
Collections.unmodifiableList(newArrayList<
(list)));
//产生不可修改的列表
}/*Output:
---ModifiableCopy---
---Arrays.asList()---
java.lang.UnsupportedOperationException
---unmodifiableList()---
java.lang.UnsupportedOperationException
因为Arrays.asList()实际上会产生一个Arraylist,它基于一个固定大小的数组,仅支持那些不会改变数组大小的操作。
所以,任何会引起对底层数据结构的尺寸进行修改的方法(add/remove相关)都会产生一个UnsupportedOperationException异常,以表示对该容器未获支持操作的调用。
因此,Arrays.asList()的真正意义在于:
将其结果作为构造器参数传递给任何Collection(或者使用addAll方法、Collections.addAll静态方法),这样可以生成一个动态的容器。
由以上程序片段可知,Arrays.asList()返回固定尺寸的List,而Collections.unmodifiableList()产生不可修改的列表。
正如输出所示,前者支持set操作,而后者不支持。
若使用接口,那么还需要两个附加的接口,一个具有可以工作的set方法,另一个没有,因为附加的接口对于Collection的各种不可修改子类型来说是必须的。
因此,可选方法可以避免接口爆炸。
针对Arrays.asList()这种情况给出解释:
1.首先该方法的源码为:
publicstatic<
T>
asList(T...a){
returnnewArrayList<
(a);
2.紧接着看上述方法所返回的由固定尺寸的数据结构支持的容器源码(部分):
privatestaticclassArrayList<
extendsAbstractList<
implementsRandomAccess,java.io.Serializable
{
privatestaticfinallongserialVersionUID=-2764017481108945198L;
privatenalE[]a;
ArrayList(E[]array){
if(array==null)
thrownewNullPointerException();
a=array;
publicintsize(){
returna.length;
publicObject[]toArray(){
returna.clone();
public<
T[]toArray(T[]a){
intsize=size();
if(a.length<
size)
returnArrays.copyOf(this.a,size,
(Class<
extendsT[]>
)a.getClass());
System.arraycopy(this.a,0,a,0,size);
if(a.length>
a[size]=null;
returna;
publicEget(intindex){
returna[index];
publicEset(intindex,Eelement){//该容器支持的操作
EoldValue=a[index];
a[index]=element;
returnoldValue;
publicintindexOf(Objecto){
for(inti=0;
i<
a.length;
i++)
if(a[i]==null)
returni;
if(o.equals(a[i]))
return-1;
returnindexOf(o)!
=-1;
....
其余代码省略
针对Add操作:
该容器的该行为继承于AbstractList抽象类,直接或间接调用add(intindex,Eelement)方法,抛出UnsupportedOperationException
//AbstractList中的方法
publicbooleanadd(Ee){
add(size(),e);
publicvoidadd(intindex,Eelement){
thrownewUnsupportedOperationExc