博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java整体集合框架(转)
阅读量:4672 次
发布时间:2019-06-09

本文共 5381 字,大约阅读时间需要 17 分钟。

1、关于集合的两道面试题

先来看几道题目:

1、创建一个不可变的的集合:

public static void main(String[] args) {      Set
set = new HashSet
(); set.add("Java"); set.add("JEE"); set.add("Spring"); set.add("Hibernate"); set = Collections.unmodifiableSet(set); set.add("Ajax"); // not allowed.}

可以看到,创建不可变集合主要是调用了Collections的unmodifiableSet()方法,而Collections类通过装饰模式实现了对一般集合的封装。

2、去除List集合中的重复元素,且保持原有的顺序

public static void main(String args[]) {          List
list=new ArrayList(); list.add("A"); list.add("B"); list.add("C"); list.add("A"); // List中允许元素重复for(int i=0;i
List
function (List
list) { return new ArrayList
(new LinkedHashSet
(list)); }

上面的代码代码通过把原有列表传入一个LinkedHashSet来去除重复的元素。在这个情况里,LinkedHashSet可以保持元素原来的顺序。如果这个顺序是不需要的话,那么上面的LinkedHashSet可以用HashSet来替换。

2、集合框架类图及集合对比

其实如上的两道题目并不难,只是没有对集合了解的更深。下面就来大概的看一下集合吧。集合的继承类如下所示。

如上的集合可以归纳为三大类,即List、Set和Map。同时还有一些辅助的工具类,像Collections、Arrays等方便了集合的操作,各个集合的比较情况如下图。

其实对于集合的操作,无外乎就是

  1. 增加:向一个集合中添加一个元素、将一个集合中的所有元素插入到当前集合中
  2. 删除:删除指定的一个元素、删除集合中所有的元素
  3. 修改:修改指定的一个元素
  4. 查找:查当前集合的大小、查找两个集合中的共同元素等
  5. 其它:如将一个集合中的元素转换为数组表示形式、判断一个集合是否为空等

3、Iterable、Iterator、Collection接口

从Java集合框架图可以看出,所有的类都直接或间接继承了Iterable接口,源代码如下:

package java.lang;  import java.util.Iterator;  /** * Implementing this interface allows an object to be the target of * the "foreach" statement. */public interface Iterable
{ Iterator
iterator(); // 返回一个在一组 T 类型的元素上进行迭代的迭代器}

Iterable接口在java.lang包下,其中定义了一个获取Iterator的实例方法。

Iterator类的源代码如下:

public interface Iterator
{ boolean hasNext(); // 是否含有下一个元素 E next(); // 获取集合的下一个元素void remove(); // 从集合中移除当前元素}

Iterator模式是用于遍历集合类的标准访问方法。它可以把访问逻辑从不同类型的集合类中抽象出来,从而避免向客户端暴露出集合的内部结构。例如,如果没有使用Iterator,遍历一个数组的方法是使用索引:

for(int i=0; i

当访问一个链表(LinkedList)时又必须使用while循环:

while((e=e.next())!=null) {   // 省略操作代码}

以上两种方法遍历办法都必须事先知道集合的内部存储结构,访问代码和集合本身是紧耦合,无法将访问逻辑从集合类中分离出来,每一种集合对应一种遍历方法,客户端代码无法复用。 而且如果以后需要把ArrayList更换为LinkedList,则原来的客户端代码必须要进行重写。 为解决以上问题,Iterator模式总是用同一种逻辑来遍历集合:

for(Iterator it = c.iterater();it.hasNext(); ) {   // ... }

设计的巧妙之处在于客户端自身不维护遍历集合的"指针",所有的内部状态(如当前元素位置,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂方法生成,因此,它知道如何遍历整个集合。值得提醒的是,这个工厂方法就是我们前面提到的iterator()方法,因为所有的类都继承了Iterable接口,所以他的实现类必须要实现iterator()方法。

以后如果要访问集合时,就可以通过控制Iterator,向它发送"向前","向后","取当前元素"的命令,来间接遍历整个集合。

public class testSet {  public static void main(String args[]) {  // HashSet
ct = new HashSet<>();// Set
ct=new HashSet<>();// List
ct=new ArrayList<>(); List
ct=new LinkedList<>(); ct.add("abc"); ct.add("def"); for(Iterator
myitr = ct.iterator();myitr.hasNext();){ System.out.println(myitr.next()); } Iterator
iter = ct.iterator(); while (iter.hasNext()) { System.out.println(iter.next()); } for (String str : ct) { System.out.println(str); } } }

使用了3种方法进行集合的遍历,输出的结果都是一致的,如下:

abc 

       def 
       abc 
       def 
       abc 
       def

每一种集合类返回的Iterator具体类型可能不同,Array可能返回ArrayIterator,Set可能返回SetIterator,Tree可能返回TreeIterator,但是它们都实现了Iterator接口,因此,客户端不关心到底是哪种Iterator,它只需要获得这个Iterator接口即可,这就是面向对象所带来的好处。

继续看Collection接口,源代码如下:

public interface Collection
extends Iterable
{ // 查找操作int size(); Iterator
iterator(); // 判断boolean isEmpty(); boolean contains(Object o); boolean containsAll(Collection
c); // 增加操作boolean add(E e); boolean addAll(Collection
c); // 删除操作boolean remove(Object o); boolean removeAll(Collection
c);// Removes all of this collection's elements that are also contained in the specified collection (optional operation).boolean retainAll(Collection
c);// Retains only the elements in this collection that are contained in the specified collection (optional operation).void clear(); // 集合转换 Object[] toArray();
T[] toArray(T[] a); // 提供equals()和hashCode()boolean equals(Object o); int hashCode(); }

Collection接口针对集合定义了一些基本的操作,所以任何一个具体的集合实现类都有含有这些方法。但是由于抽象层次较高,所以一般一个具体的集合实现类,如ArrayList、HashMap等都不会直接继承这个接口,而是继承这个接口的一些子类来实现。所以说每个集合的具体实现类都直接或间接继承了这个接口。

有一类重要的方法还需要说明一下:

boolean add(E e);  boolean addAll(Collection
c); boolean remove(Object o); boolean removeAll(Collection
c);

拿add(E e)方法来举例,这个方法将在集合中添加一个新的元素。方法会返回一个boolean,但是返回值不是表示添加成功与否。仔细阅读doc可以看到,Collection规定:如果一个集合拒绝添加这个元素,无论任何原因,都必须抛出异常。这个返回值表示的意义是add()方法执行后,集合的内容是否改变了(就是元素有无数量,位置等变化),这是由具体类实现的。即:如果方法出错,总会抛出异常;返回值仅仅表示该方法执行后这个Collection的内容有无变化。

观察发现传入的参数有许多都是Collection<?>类型的,这就为各个集合的具体实现类实现相互的操作提供了便利。举个例子:

LinkedList
list=new LinkedList<>(); list.add("xy"); list.add("mn"); Collection
ct=new HashSet
(); ct.add("abc"); ct.add("def"); ct.addAll(list); Iterator
iter=ct.iterator(); while(iter.hasNext()){ System.out.println(iter.next()); }

将LinkedList集合中的元素添加到HashSet中,只需要调用addAll()方法即可。最后结果输出如下: 

mn 
abc 
def 
xy

作者:
出处:
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

转载于:https://www.cnblogs.com/dayhand/p/3613033.html

你可能感兴趣的文章
snort简介以及在Ubuntu下的安装
查看>>
从SVN资源库下载项目
查看>>
Class.isAssignableFrom(Class clz)方法 与 instanceof 关键字的区别
查看>>
php克隆 自动加载
查看>>
删除同目录下面txt文件(利用os,fnmacth模块)
查看>>
sqlserver 按日、周、月统计方法
查看>>
简单几步让CentOS系统时间同步
查看>>
Host aggregate分区
查看>>
Windows服务器上使用phpstudy部署PHP程序
查看>>
[唐胡璐]QTP框架 - 关键字驱动测试框架之三 - 对象库管理
查看>>
zoj 2112 树状数组 套主席树 动态求区间 第k个数
查看>>
4538: [Hnoi2016]网络
查看>>
186. [USACO Oct08] 牧场旅行
查看>>
一个屌丝程序猿的人生(三十九)
查看>>
Linux常用命令
查看>>
Spring之@Configuration配置解析
查看>>
Windows操作系统远程Linux服务器传输文件方法(以EasyDSS云平台、EasyNVR上传部署为例)...
查看>>
pip安装第三方库以及版本
查看>>
一、app更新提示后台接口开发-(2)数据库表设计
查看>>
利用data-src属性 更换图片
查看>>