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

先来看几道题目:

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

    public static void main(String[] args) {
    Set<String> set = new HashSet<String>();
    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<String> list=new ArrayList();
    list.add("A");
    list.add("B");
    list.add("C");
    list.add("A");
    // List中允许元素重复
    for(int i=0;i<list.size();i++)
    System.out.print(" "+list.get(i));// A B C A
    // 去除重复的元素且保持原有元素的顺序
    List list2=new testD().function(list);
    for(int i=0;i<list2.size();i++)
    System.out.print(" "+list2.get(i));// A B C }
    public <e> List<e> function (List<e> list) {
    return new ArrayList<e>(new LinkedHashSet<e>(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<T> {
    Iterator<T> iterator(); // 返回一个在一组 T 类型的元素上进行迭代的迭代器
    }

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

Iterator类的源代码如下:

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

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

    for(int i=0; i<集合的大小;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<String> ct = new HashSet<>();
    // Set<String> ct=new HashSet<>();
    // List<String> ct=new ArrayList<>();
    List<String> ct=new LinkedList<>(); ct.add("abc");
    ct.add("def"); for(Iterator<String> myitr = ct.iterator();myitr.hasNext();){
    System.out.println(myitr.next());
    } Iterator<String> 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<E> extends Iterable<E> {
    // 查找操作
    int size();
    Iterator<E> iterator(); // 判断
    boolean isEmpty();
    boolean contains(Object o);
    boolean containsAll(Collection<?> c); // 增加操作
    boolean add(E e);
    boolean addAll(Collection<? extends E> 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> T[] toArray(T[] a); // 提供equals()和hashCode()
    boolean equals(Object o);
    int hashCode();
    }

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

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

    boolean add(E e);
    boolean addAll(Collection<? extends E> c); boolean remove(Object o);
    boolean removeAll(Collection<?> c);

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

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

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

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

mn

abc

def

xy

java整体集合框架的更多相关文章

  1. java的集合框架最全详解

    java的集合框架最全详解(图) 前言:数据结构对程序设计有着深远的影响,在面向过程的C语言中,数据库结构用struct来描述,而在面向对象的编程中,数据结构是用类来描述的,并且包含有对该数据结构操作 ...

  2. java.util 集合框架集合

    java的集合框架为程序提供了一种处理对象组的标准方式.设计了一系列标准泛型接口: ⑴Collection ()接口,扩展了Iterable接口,位于集合层次结构的顶部,因此所有的集合都实现Colle ...

  3. Java基础——集合框架

    Java的集合框架是Java中很重要的一环,Java平台提供了一个全新的集合框架.“集合框架”主要由一组用来操作对象的接口组成.不同接口描述一组不同数据类型.Java平台的完整集合框架如下图所示: 上 ...

  4. java的集合框架之一

    java是一套很成熟的东西,很多商用的东西都喜欢用它,用的人多,稳定.不过一般也不怎么说起它,因为太常见了,私下里说,写java应用层得就像农民工,每一处都是搭积木,根据设计师的东西如何优雅地搭好积木 ...

  5. 浅谈Java的集合框架

    浅谈Java的集合框架 一.    初识集合 重所周知,Java有四大集合框架群,Set.List.Queue和Map.四种集合的关注点不同,Set 关注事物的唯一性,List 关注事物的索引列表,Q ...

  6. java的集合框架set 和map的深入理解

    Java的集合框架之Map的用法详解 Map有两种比较常用的实现:HashMap 和 TreeMap. HashMap: HashMap 也是无序的,也是按照哈希编码来排序的,允许使用null 值和n ...

  7. Java 高级-集合框架

    参考资料 参考 HashMap 类似 C++ 中的 STL 标准模板库,Java 也在 java.util 包中封装了一套常用数据结构及其算法,称为集合框架.所有的集合框架都包含如下内容: 接口:代表 ...

  8. Java 之集合框架 上(9)

    Java 中的集合框架 如果一个类中存在很多相同类型的属性. 例如:学生类 学生可以选课,因此存在很多课程类型的属性.但是每个学生选择的课程的种类和数量是不一样的. 如果将每一个课程类型的属性都列到课 ...

  9. Java 之 集合框架(JCF)

    1.集合框架 a.框架:为了实现某一目的或功能,而预先提供的一系列封装好的.具有继承或实现关系的类与集合 b.集合:①定义:Java中对一些数据结构和算法进行封装,即封装(集合也是一种对象) ②特点: ...

随机推荐

  1. Android studio教程:[6]创建多个Activity

    通常来说,一个android应用程序不止一个Activity(活动),更不止一个界面.于是需要创建多个Activity来满足应用程序的要求,这里我将告诉大家如何添加新的Activity,并实现Acti ...

  2. (转+原)android获取系统时间

    参考的网站如下: http://c.biancheng.net/cpp/html/144.html http://www.linuxidc.com/Linux/2012-03/55909.htm 代码 ...

  3. j2ee基础

    1.tomcat端口被占用解决方式 使用netstat -anb查看哪个进程占用,禁止掉 修改tomacat使用的端口,在配置文件conf/server.xml 2.web app目录 3.如何建立虚 ...

  4. 移动端-弹窗demo

    <!doctype html> <html> <head> <meta charset="UTF-8"> <meta name ...

  5. C语言学习笔记frist---输入两个数比较大小

    C#学习中,问道艰辛,今自C学起,第一个函数学习:输入两个数比较大小,仅作练习: #include "stdafx.h" #include<stdio.h> // 包含 ...

  6. VS2012常用快捷建(必备)

    1. 强迫智能感知:Ctrl+J:2.强迫智能感知显示参数信息:Ctrl-Shift-空格:3.格式化整个块:Ctrl+K+F4. 检查括号匹配(在左右括号间切换): Ctrl +]5. 选中从光标起 ...

  7. EntityFramework+Autofac+MVC+EasyUI 搭建公司基本服务项目

    去年年底用了2个星期的时间搭建了 这套框架,从ORM,IOC,MVC,EasyUI都仔细的研究了下,还有日志,异常等等.mvc 我已经开发过很多项目了,我就觉得自己写套框架,看看自己的水平如何.欢迎大 ...

  8. create custom launcher icon 细节介绍

    create custom launcher icon 是创建你的Android app的图标 点击下一步的时候,出现的界面就是创建你的Android的图标 Foreground: ” Foregro ...

  9. android的listview组件

    http://www.cnblogs.com/menlsh/archive/2013/03/15/2962350.html http://www.tuicool.com/articles/IveeI3 ...

  10. 悼念512汶川大地震遇难同胞――珍惜现在,感恩生活 分类: dp 2015-05-21 10:50 14人阅读 评论(0) 收藏

    Description 急!灾区的食物依然短缺! 为了挽救灾区同胞的生命,心系灾区同胞的你准备自己采购一些粮食支援灾区,现在假设你一共有资金n元,而市场有m种大米,每种大米都是袋装产品,其价格不等,并 ...