概述


通过前文的学习,我们对容器的分类常用容器类的作用有了基本的认识。本文将针对Collection容器的功能与使用进行细致分析。

基本操作


Collection集合抽象出的目的是为存放独立元素的序列。

Collection接口定义的基本操作包含添加,移除,查找,遍历等。具体API定义如下:

abstract boolean add(E e)
abstract boolean addAll(Collection<? extends E> c)
abstract boolean clear()
abstract boolean contains(Object o)
abstract boolean containsAll(Collection<? extends E> c)
abstract boolean equals(Object o)
abstract int hashCode()
abstract boolean isEmpty()
abstract Iterator<E> iterator()
abstract boolean remove(Object o)
abstract boolean removeAll(Collection<?> c)
abstract boolean retainAll(Collection<?> c)
abstract int size()
abstract Object[] toArray()
abstract <T> T[] toArray(T[] a)

这些操作可以按照具体作用来划分,下面我们结合一些实例来理解。

添加元素


package collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; public class Adding {
public static void main(String[] args) {
//构造方法直接添加
Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4));
//使用add方法
collection.add(5);
System.out.println(collection);
Integer[] Ints = {10, 11, 12};
//使用addAll方法
collection.addAll(Arrays.asList(Ints));
System.out.println(collection);
//Collections提供的addAll方法
Collections.addAll(collection, Ints);
System.out.println(collection);
}
}

输出结果

[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 10, 11, 12]
[1, 2, 3, 4, 5, 10, 11, 12, 10, 11, 12]

本例中,Arrays的asList方法可将数组转换为List类型,我们可以通过构造方法直接初始化Collection实例。若想添加单个元素,直接调用add方法;想要添加一组元素,也可调用addAll方法。另一种比较高效方式是调用Collections的addAll方法。

辨析 Collection Collections

Collection与Collections同属于集合类,但却完全不同。这是Java开发者非常容易混淆的内容。

Collection是集合的顶层接口,而Collections则是一个工具类。Collections提供了许多静态方法,从而能够操作集合,对集合中的元素进行排序,添加以及搜索等操作。例如:

排序

package collections;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TestCollections1{
public static void main(String[] args){
Integer[] a = {10, 30, 20, 9, 4, 1, 50};
List<Integer> list = new ArrayList<Integer>();
Collections.addAll(list, a);
System.out.println(list);
Collections.sort(list);
System.out.println(list);
}
}

输出结果

[10, 30, 20, 9, 4, 1, 50]
[1, 4, 9, 10, 20, 30, 50]

Collections中实用的方法还有很多,下面列出一些常用方法的API,本文就不再一一赘述。

public static <T> boolean addAll(Collection<? super T> c, T... elements)
//二分搜索搜索列表指定元素
public static <T> int binarySearch(List<? extends T>, T key)
//将元素从一个列表复制到到另一个列表
public static <T> void copy(List<? super T> dest, List<? extends T> src);
//反转列表
public static void reverse(List<?> list)
//随机化列表
public static void shuffle(List<T> list)
//返回线程安全的collection
public static <T> Collection<T> synchronizedCollection(Collection<T> c)
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
public static <T extends Object & Comparable<? super T>> T min(Collection<? extends T> coll)

删除元素


package collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; public class Removing{
public static void main(String[] args) {
String[] arr = {"I'm sorry","I'm coding", "I'm writing", "I'm learning", "I'm thinking"};
Collection<String> collection = new ArrayList<String>(Arrays.asList(arr));
Collection<String> c = new ArrayList<String>(Arrays.asList("I'm learning", "I'm thinking"));
System.out.println(collection);
//移除元素
collection.remove("I'm writing");
System.out.println(collection);
//移除一组元素
collection.removeAll(c);
System.out.println(collection);
//移除所有元素
collection.clear();
System.out.println(collection);
}
}

输出结果

[I'm sorry, I'm coding, I'm writing, I'm learning, I'm thinking]
[I'm sorry, I'm coding, I'm learning, I'm thinking]
[I'm sorry, I'm coding]
[]

本例中,调用remove方法删除集合中单个元素,通过removeAll方法删除一组包含于collection中的元素,使用clear方法可移除集合所有元素。

访问元素


观察Collection定义的API可看出,Collection接口似乎没有对访问指定位置元素,遍历列表提供合适的方法。containsequals两种方法可查找元素,却也无法实现迭代,遍历元素的目的。

这时就需要Iterator(迭代器)来为我们帮忙了,Collection中iterator()方法直接返回容器的Iterator,以遍历整个容器。

迭代器


迭代器(Iterator)这一概念源自C++的STL(标准模板库),使用者可直接遍历容器而无需关心其结构类型,直接使用Iterator即可。Java中,Iterator的限制是只能单向遍历容器

用法


Iteraotr提供了以下三种方法

boolean hasNext()
E next()
void remove()

hasNext方法用于确定容器中是否还有元素,next方法获得容器中下一个元素,remove方法删除Iterator目前指向的元素。

举个栗子

package collection;

import java.util.*;

public class EasyIteration{
public static void main(String[] args){
Integer[] Ints = {1, 2, 3, 8, 5};
Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(Ints));
Iterator<Integer> it = collection.iterator();
//遍历开始,hasNext控制边界
while(it.hasNext()){
System.out.print(it.next()+" ");
}
System.out.println();
it = collection.iterator();
for(int i = 0; i < 2; i++){
it.next();
//删除元素
it.remove();
}
System.out.println(collection);
}
}

输出结果

1 2 3 8 5
[3, 8, 5]

本例中,有了Iterator,我们就可以对容器中的元素进行访问和删除操作,而无需关心容器的具体类型。

UnspportedOperationException异常


UnspportedOperationException抛出的原因是使用了不当的容器操作。通常是由于尝试修改固定长度的容器的缘故,调用Array.asList() 方法会返回这种容器。因为数组显然是固定长度的容器,使用asList方法转换为list也会保持这种属性。

举个栗子

package collection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections; public class UnspportedTest{
public static void test(String msg, Collection<Integer> collection){
Integer[] arr = {1, 3, 4};
Collection<Integer> tc = Arrays.asList(arr);
//使用会修改容器的操作
System.out.println("****" + msg + "****");
try{
collection.add(5);
}catch(Exception e){
e.printStackTrace();
}
try{
Collections.addAll(collection, arr);
}
catch(Exception e){
e.printStackTrace();
}
try{
collection.retainAll(tc);
}
catch(Exception e){
e.printStackTrace();
}
try{
collection.remove(1);
}catch(Exception e){
e.printStackTrace();
}
try{
collection.removeAll(Arrays.asList(arr));
} catch(Exception e){
e.printStackTrace();
}
} public static void main(String[] args){
Integer[] arr = {1, 3, 1, 4, 1, 2};
Collection<Integer> c = Arrays.asList(arr);
Collection<Integer> c1 = new ArrayList<Integer>(c); test("可修改", c1);
test("不可修改", c);
test("不可修改", Collections.unmodifiableCollection(c1));
}
}

输出结果

****可修改****
****不可修改****
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at collection.UnspportedTest.test(UnspportedTest.java:13)
at collection.UnspportedTest.main(UnspportedTest.java:47)
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:148)
at java.util.AbstractList.add(AbstractList.java:108)
at java.util.Collections.addAll(Collections.java:3845)
at collection.UnspportedTest.test(UnspportedTest.java:18)
at collection.UnspportedTest.main(UnspportedTest.java:47)
java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at java.util.AbstractCollection.remove(AbstractCollection.java:291)
at collection.UnspportedTest.test(UnspportedTest.java:30)
at collection.UnspportedTest.main(UnspportedTest.java:47)
java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at java.util.AbstractCollection.removeAll(AbstractCollection.java:373)
at collection.UnspportedTest.test(UnspportedTest.java:35)
at collection.UnspportedTest.main(UnspportedTest.java:47)
****不可修改****
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1075)
at collection.UnspportedTest.test(UnspportedTest.java:13)
at collection.UnspportedTest.main(UnspportedTest.java:48)
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1075)
at java.util.Collections.addAll(Collections.java:3845)
at collection.UnspportedTest.test(UnspportedTest.java:18)
at collection.UnspportedTest.main(UnspportedTest.java:48)
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.remove(Collections.java:1078)
at collection.UnspportedTest.test(UnspportedTest.java:30)
at collection.UnspportedTest.main(UnspportedTest.java:48)
java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.removeAll(Collections.java:1088)
at collection.UnspportedTest.test(UnspportedTest.java:35)
at collection.UnspportedTest.main(UnspportedTest.java:48)

本例中,test方法包含了会修改数组长度的方法。为其传入固定长度的容器引用,会抛出UnspportedOperationException异常。

输出结果可知,若在为容器分配空间时将asList方法得到的list通过构造方法初始化,会得到一个尺寸可调的Collection实例,允许调用所有方法。 若直接将asList生成的list返回给容器实例,就会附加不可修改尺寸的属性,抛出异常。 最后我们证明了调用Collections工具类的unmodifiableCollection方法可人为的给普通容器加上不可修改的特性,同样会抛出UnspportedOperationException异常。

总结


Collection接口是容器类最上层的接口之一,一般通过向上转型的方式来实现该接口。本文针对Collection定义的基本操作功能与用途,与Collections的关系,以及因不当操作而可能抛出的UnspportedOperationException异常进行了深入的分析。

后续,将继续和大家讨论继承Collection接口的List,Set,Queue 以及 Map的基本操作与机制。


作者: I'm coding

链接ACFLOOD

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

如果您觉得本文对您有所帮助,就给俺点个赞吧!

走进Java中的持有对象(容器类)【二】Collection的更多相关文章

  1. 走进Java中的持有对象(容器类)之一 容器分类

    Java容器可以说是增强程序员编程能力的基本工具,本系列将带您深入理解容器类. 容器的用途 如果对象的数量与生命周期都是固定的,自然我们也就不需要很复杂的数据结构. 我们可以通过创建引用来持有对象,如 ...

  2. (转)java中对集合对象list的几种循环访问总结

    Java集合的Stack.Queue.Map的遍历   在集合操作中,常常离不开对集合的遍历,对集合遍历一般来说一个foreach就搞定了,但是,对于Stack.Queue.Map类型的遍历,还是有一 ...

  3. java中的常用类(二)

    java中的常用类(二) Math类 Math类的声明:public final class Math extends Object Math类是与数学计算有关的类,里面的方法都是静态方法,直接使用类 ...

  4. java中对集合对象list的几种循环访问

    java中对集合对象list的几种循环访问的总结如下 1 经典的for循环 public static void main(String[] args) { List<String> li ...

  5. Java中的函数对象

    初次听说java中的函数对象可能,比较的陌生.可以类比着来理解一下,人们常说java中没有了指针,殊不知,java中的对象引用就是指针,有时候我们说一个对象往往指的就是这个对象的引用,也就是说基本上把 ...

  6. Java中创建实例化对象的几种方式

    Java中创建实例化对象有哪些方式? ①最常见的创建对象方法,使用new语句创建一个对象.②通过工厂方法返回对象,例:String s =String.valueOf().(工厂方法涉及到框架)③动用 ...

  7. Java中字节与对象之间的转换

    近期公司里面用到了消息队列,而正如我们知道的是消息队列之间的是通过二进制形式的.以下就分享一下java中字节与对象之间的转换. 主要是用到了ByteArrayOutputStream和ObjectOu ...

  8. java中的string对象深入了解

    这里来对Java中的String对象做一个稍微深入的了解. Java对象实现的演进 String对象是Java中使用最频繁的对象之一,所以Java开发者们也在不断地对String对象的实现进行优化,以 ...

  9. Java中创建的对象多了,必然影响内存和性能

    1, Java中创建的对象多了,必然影响内存和性能,所以对象的创建越少越好,最后还要记得销毁.

随机推荐

  1. UVA - 116 Unidirectional TSP 多段图的最短路 dp

    题意 略 分析 因为字典序最小,所以从后面的列递推,每次对上一列的三个方向的行排序就能确保,数字之和最小DP就完事了 代码 因为有个地方数组名next和里面本身的某个东西冲突了,所以编译错了,后来改成 ...

  2. Linux内核分析第四章 读书笔记

    Linux内核分析第四章 读书笔记 第一部分--进程调度 进程调度:操作系统规定下的进程选取模式 面临问题:多任务选择问题 多任务操作系统就是能同时并发地交互执行多个进程的操作系统,在单处理器机器上这 ...

  3. 第七周linux内核分析

    可执行程序的装载 作者 黎静+ 原创作品转载请注明出处 + <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-100002900 ...

  4. Beta版发布说明

    我们的作品“校友聊”软件的最终版本于6月19日最终发布了,下面我们将对自己的产品进行介绍. 在使用之前,首先要进行用户注册,用户可以自行设置自己的账号,姓名,密码,签名,头像等信息,头像信息也可以在文 ...

  5. 【软件工程】5.8 黑盒&白盒测试

    代码链接:http://www.cnblogs.com/bobbywei/p/4469145.html#3174062 搭档博客:http://www.cnblogs.com/Roc201306114 ...

  6. Alpha 答辩总结模板

    Alpha 答辩总结模板 每个小组提供一篇总结博客(组内共享,每个人都发布),包含: 本组(组名)所有成员(短学号,名,标注组长)(1分) 组内各成员贡献比例,如不提供,取平均分后组长得分减50% G ...

  7. JavaScript解决一个带验证的Form两个Submit事件(一个页面保持不动【AJAX实现】,一个页面提交并跳转)的场景

    <form class="form-horizontal" action="/biz/patent/edit" method="post&quo ...

  8. VMware安装win7提示 operating system not found

    在虚拟机上安装win7时,进度条读完,重启后提示operating system not found,可能原因是在使用分区工具格式化时没有把C盘设置为主分区并激活. 解决办法: 进入PE或者使用分区工 ...

  9. 2016_NENU_CS_3

    贴一下比赛的代码,  其中 I 题代码源于final大神 ok_again http://acm.hust.edu.cn/vjudge/contest/127444#overview I /***** ...

  10. target存放的是编译后的.class文件地方 默认情况下不会讲非class文件放入进入 如果要使用非.class文件 需要通过增加配置方式自动加入文件

    target存放的是编译后的.class文件地方 默认情况下不会讲非class文件放入进入 如果要使用非.class文件 需要通过增加配置方式自动加入文件