Java中的集合框架学习之Collection 详解

前言:一名iOS开发工程师,正在学习Android开发,期待各路大神指点和学习交流.
学习交流讨论及资料获取请关注:极客James

一.为什么出现集合类?##

面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就要对对象进行存储,集合就是存储对象最常用的一种方式。

数组和集合类同是容器,有何不同?

数组虽然也可以存储对象,但长度是固定的;集合长度是可变的。数组中可以存储任意数据类型,集合只能存储对象。

集合类的特点

集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

我的总结:集合类比数组强大,类似于包装类与基本数据类型!

二.集合框架的构成及分类

f4220ed767a67cd4a144dfce.jpg

根据上图可以直观的看出集合框架中的两大接口:
Java集合类主要由两个接口派生出来:

Collection

Set :不能存放重复对象
List :可存放重复对象,有序
Queue :队列
SortedSet :可对集合数据排序

Map

SortedMap :可对集合数据排序

Collection接口

2016-07-29_111650.png
public class Demo10 {
    public static void main(String[] args) {
        Collection<String> c = new ArrayList<String>();
        c.add("A");
        c.add("A");
        c.add("A");
        c.add("A");
        System.out.println(c);
}
}

Iterator接口

对 collection 进行迭代的迭代器。迭代器取代了 Java Collections Framework 中的 Enumeration。


2016-07-29_112050.png
Iterator iter = l.iterator();
while(iter.hasNext()){
    System.out.println(iter.next());
}
集合遍历输出方式

1.Iterable接口(迭代遍历) 注:优先选择Iterator接口,遍历Collection里所有元素,也称为迭代器和迭代精灵;迭代是取出集合中元素的一种推荐方式。
2.Foreach循环 注:可以直接用,使用场合:数组和Iterable对象!
3.For循环 注:在()内实例化Iterable对象,进行遍历!
4.先用toArray方法输出成为数组,再用Foreach循环!

// 四种遍历方法的代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class Demo11 {
    public static void main(String[] args) {

        List<String> l = new ArrayList();

        l.add("1");
        l.add("2");
        l.add("3");
        l.add("4");

        System.out.println(l);
        /**
         * 遍历输出:四种方式
         */

        // 1、推荐使用的Iterator对象,迭代输出!
        Iterator it = l.iterator();
        while (it.hasNext()) {
            System.out.println("迭代输出:" + it.next());
        }

        // 2、对集合进行fore循环!
        for (String str : l) {
            System.out.println("fore集合迭代输出:" + str);
        }

        // 3、for循环迭代,在for方法体内部实例化Iterator对象!
        int i = 0;// for方法体内定义项不能出现多种不同类型
        for (Iterator iter = l.iterator(); i < l.size(); i++) {
            System.out.println("for循环迭代实例化输出:" + iter.next());
        }

        // 4、先将集合转换为数组,再利用数组的遍历输出;
        Object[] o = l.toArray();
        for (Object object : o) {
            System.out.println("转换数组迭代输出:" + object);
        }
    }
}

Set接口

一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。

在所有构造方法以及 add、equals 和 hashCode 方法的协定上,Set 接口还加入了其他规定,这些规定超出了从 Collection 接口所继承的内容。出于方便考虑,它还包括了其他继承方法的声明(这些声明的规范已经专门针对 Set 接口进行了修改,但是没有包含任何其他的规定)。

对这些构造方法的其他规定是(不要奇怪),所有构造方法必须创建一个不包含重复元素的 set(正如上面所定义的)。

注:如果将可变对象用作 set 元素,那么必须极其小心。如果对象是 set 中某个元素,以一种影响 equals 比较的方式改变对象的值,那么 set 的行为就是不确定的。此项禁止的一个特殊情况是不允许某个 set 包含其自身作为元素。

某些 set 实现对其所包含的元素有所限制。例如,某些实现禁止 null 元素,而某些则对其元素的类型所有限制。试图添加不合格的元素会抛出未经检查的异常,通常是 NullPointerException 或 ClassCastException。试图查询不合格的元素是否存在可能会抛出异常,也可能简单地返回 false;某些实现会采用前一种行为,而某些则采用后者。概括地说,试图对不合格元素执行操作时,如果完成该操作后不会导致在 set 中插入不合格的元素,则该操作可能抛出一个异常,也可能成功,这取决于实现的选择。此接口的规范中将这样的异常标记为“可选”。

我的总结:

#######很重要的一点:理解!往HashSet集合里面存入数据,要先后调用两个方法:hashCode方法和equals方法!!!

Set接口常用方法
//hashset方法和equals方法判断输入的对象是否重复!

import java.util.HashSet;
import java.util.Set;

class PersonDemo{
    private String name;

    public PersonDemo(String name) {
        super();
        this.name = name;
    }

    @Override
    public String toString() {
        return "name= " + name ;
    }
    //没有覆写hashcode和equals方法前,显示三次(一样的)。覆写后,只剩下一个了!说明覆写后方法起作用了,重复的输入不进去!
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        PersonDemo other = (PersonDemo) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

public class Demo12 {
    public static void main(String[] args) {
        
        Set s = new HashSet();
        
        s.add(new PersonDemo("章泽天"));
        s.add(new PersonDemo("章泽天"));
        s.add(new PersonDemo("章泽天"));
        System.out.println(s);
    }
}   

TreeSet

TreeSet是SortedSet接口唯一的实现,与HashSet相比额外的方法有:
Comparator comparator():返回当前Set使用的Comparator,若返回null,表示以自然顺序排序。
Object first() 返回此 set 中当前第一个(最低)元素。
Object last() 返回此 set 中当前最后一个(最高)元素。
SortedSet subSet(Object fromElement, E toElement) 返回此 set 的部子集,其元素从 fromElement(包括)到 toElement(不包括)。
SortedSet headSet(Object toElement)返回此 set 的部分子集,其元素严格小于 toElement。
SortedSet tailSet(Object fromElement) 返回此 set 的部分子集,其元素大于等于 fromElement。

TreeSet的排序之自然排序

TreeSet会调用元素的compareTo(Object o)方法来比较元素之间的大小关系,然后将集合里的元素按升序排列.此时需要排序元素的类必须实现Compareble接口,并覆写其int compareTo(Object o)方法;
该方法用于比较对象,若:obj1,compareTo(obj2),返回0,表示两个对象相等,若返回一个正整数,表示obj1大于obj2,若返回一个负整数,表示obj1小于obj2;
对于TreeSet集合而言,判断两个对象相等的标准是:
compareTo()方法比较返回 0;

//TreeSet可以自动进行排序!最简单的情况

import java.util.Set;
import java.util.TreeSet;

public class Demo13 {
    public static void main(String[] args) {
        
        Set<Integer> s = new TreeSet<Integer>();
        s.add(1);
        s.add(192);
        s.add(123);
        
        s.add(56);
        s.add(13);
        s.add(96);
        System.out.println(s);//[1, 13, 56, 96, 123, 192]
    }
}

稍复杂点的

package july7;
//TreeSet的自然排序,升序

import java.util.Set;
import java.util.TreeSet;

class Student implements Comparable{//必须实现接口
    private Integer age;

    public Student(Integer age) {
        super();
        this.age = age;
    }

    @Override
    public int compareTo(Object o) {//比较的规则,运用泛型可以消除强转!
        if(o instanceof Student){
            Student s = (Student)o;
            return this.age.compareTo(s.age);
        }
        return 0;
    }

    @Override
    public String toString() {
        return age+"" ;
    }
}

public class Demo14 {
    public static void main(String[] args) {
        
        Set<Student> s = new TreeSet();
        s.add(new Student(140));
        s.add(new Student(15));
        s.add(new Student(11));
        s.add(new Student(63));
        s.add(new Student(96));
        System.out.println(s);//[11, 15, 63, 96, 140]
    }
}
TreeSet的排序之定制排序

TreeSet的自然排序是根据元素的大小进行升序排序的,若想自己定制排序,比如降序排序,就可以使用Comparator接口了:
该接口包含int compare(Object o1,Object o2)方法,用于比较两个对象的大小,比较结果和compareTo方法一致;
要实现定制排序,需要在创建TreeSet集合对象时,提供一个一个Comparator对象,该对象里负责集合元素的排序逻辑;
TreeSet(Comparator comparator)

import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;

class Student1{
    private Integer age;
    
    public Student1(Integer age) {
        super();
        this.age = age;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return age + "";
    }
}

class MyComparator implements Comparator{
    
    @Override
    public int compare(Object o1, Object o2) {
        if(o1 instanceof Student1 & o2 instanceof Student1){
            Student1 s1 = (Student1)o1;
            Student1 s2 = (Student1)o2;
            if(s1.getAge() > s2.getAge()){
                return -1;
            }else if(s1.getAge() < s2.getAge()){
                return 1;
            }
        }
        return 0;
    }
}

public class Demo15 {
    public static void main(String[] args) {
        Set<Student1> s = new TreeSet(new MyComparator());
        /**
         * 要实现定制排序,需要在创建TreeSet集合对象时,提供一个一个Comparator对象,
         * 该对象里负责集合元素的排序逻辑;
         */
        s.add(new Student1(140));
        s.add(new Student1(15));
        s.add(new Student1(11));
        s.add(new Student1(63));
        s.add(new Student1(96));
        
        System.out.println(s);
    }
}

List接口

Collection的一个子接口;

List是有序的集合,集合中每个元素都有对应的顺序序列。List集合可使用重复元素,可以通过索引来访问指定位置的集合元素(顺序索引从0开始),List集合默认按元素的添加顺序设置元素的索引,比如第一个元素的索引就是0,好似数组。
List作为Collection子接口当然拥有其所有方法,同时也有自己的方法:

void add(int index,Object e):将元素e添加到List集合中的index处;
boolean addAll(int index,Collection c):将集合c所包含的所有元素都插入在List集合的index处;
Object get(int index):返回集合index索引处的元素;
int indexOf(Object o):返回对象o在List集合中第一次出现位置的索引;
int lastIndexOf(object o):返回对象o在List集合中最后一次出现的位置索引;
Object remove(int index):删除并返回index索引处的元素;
Object set(int index,Object e):把集合index处的元素替换为e对象,返回以前在指定位置的元素;
List subList(int fromIndex,int toIndex):返回从所有fromIndex(包括)到toIndex(不包括)处所有集合元素的子集合。

ListIterator

Iterator的子接口,专门用于操作List集合的输出;
List自己还有一个listIterator()方法,该方法返回ListIterator对象,ListIterator继承了Iterator接口,提供了专门操作List的方法。在Iterator上额外增加的方法:
支持双向输出:
boolean hasPrevious():返回该迭代器关联集合是否还有上一个元素;
Object previous():返回该迭代器的上一个元素;

我的总结:这是相对更加特殊的一个接口,只用于List集合,可以完成逆序输出!
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

public class Demo16 {
    public static void main(String[] args) {
        List<Integer> l = new ArrayList<Integer>();
        l.add(12);
        l.add(24);
        l.add(36);
        l.add(23);
        l.add(37);
        
        System.out.println(l);
        
        ListIterator<Integer> it = l.listIterator();
        while(it.hasNext()){
            System.out.println("正序:"+it.next());
        }
        System.out.println("==================================");
        //使用向前迭代前必须将游标(指针)移动到后边!
        while(it.hasPrevious()){
            System.out.println("逆序:"+it.previous());
        }
    }
}

输出:
[12, 24, 36, 23, 37]
正序:12
正序:24
正序:36
正序:23
正序:37
==================================
逆序:37
逆序:23
逆序:36
逆序:24
逆序:12

List接口中常用类

Vector:线程安全,但速度慢,已被ArrayList替代。
ArrayList:线程不安全,查询速度快。
LinkedList:链表结构,增删速度快。取出List集合中元素的方式:

get(int index):通过脚标获取元素。
iterator():通过迭代方法获取迭代器对象。
ArrayList和Vector类都是基于数组实现的List类,Vector比较古老,被ArrayList取代了;
ArrayList是线程不安全的,而Vector是线程安全的,但是即使这样,也不推荐使用Vector,因为Collections有方法可以得到线程安全的ArrayList对象;
Collections类: static List synchronizedList(List list) 返回指定列表支持的同步(线程安全的)列表。

Queue接口

继承Collection接口
模拟队列:先进先出(FIFO);
void add(Object e):将e插入到队列尾部;
Object element():获取队列头部的元素;
boolean offer(Object e):将e插入到队列的尾部,当使用有容量限制的队列时,此方法比add(Object e)方法更好。
Object peek():获取队列头部的元素。如果此双端队列为空,则返回 null。
Object poll():获取并删除队列头部的元素。如果此双端队列为空,则返回 null。
Object remove():获取并删除队列头部的元素。

List的使用
设计Department  和 Employee 对象类(按照开发的样式没有写在一个文件里面)
//一个员工只可以有一个部门,所以按照普通的写法
//一个部门可以有许多员工,所以按照集合的写法;


//员工
package re538.Department;

public class Emp {
    private Dept dept;//一个员工只可以有一个部门,所以按照普通的写法
    private String name;
    public Dept getDept() {
        return dept;
    }
    public void setDept(Dept dept) {
        this.dept = dept;
    }
    public Emp(String name) {
        super();
        this.name = name;
    }
    public String toString(){//覆写toString方法
        return this.name+"";
    }
}


//部门
package re538.Department;

import java.util.List;
public class Dept {
    private String name;
    private List emp;//一个部门可以有许多员工,所以按照集合的写法;部门里的属性,员工!
    public Dept(String name) {
        super();
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public List getEmp() {
        return emp;
    }
    public void setEmp(List emp) {
        this.emp = emp;
    }
    private Dept parent;//一个部门只有一个直接主管部门,所以普通写法
    private List children;//但是一个部门可以管理很多部门,充当很多部门的直接主管部门,所以使用集合
    public Dept getParent() {
        return parent;
    }
    public void setParent(Dept parent) {
        this.parent = parent;
    }
    public List getChildren() {
        return children;
    }
    public void setChildren(List children) {
        this.children = children;
    }
    public String toString(){
        return this.name.toString();
    }
}

//测试类,主方法!

package re538.Department;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class TestDemo {

    public static void main(String[] args) {
        Emp e1 = new Emp("刘亦菲");
        Emp e2 = new Emp("章泽天");
        Emp e3 = new Emp("张月娟");
        Emp e4 = new Emp("王二五");
        Emp e5 = new Emp("刘昭");
        List list = new ArrayList();//把员工丢尽集合去
        list.add(e1);
        list.add(e2);
        list.add(e3);
        list.add(e4);
        list.add(e5);
        for (Object object : list) {//把员工给遍历出来,使用的是直接的foreach(四种方法之一)
            System.out.println("----->"+object);
        }
        System.out.println("-------------------");
        Dept d = new Dept("部门");//定义出一个部门来接收员工
        d.setEmp(list);//把员工这个集合丢到部门去。
        Dept d1 = new Dept("itcast");
        Dept cditcast = new Dept("运维部门");
        Dept gzitcast = new Dept("IT部门");
        Dept d4 = new Dept("CSDN");
        System.out.println(d4);
        List children = new ArrayList();
        children.add(cditcast);
        children.add(gzitcast);
        d1.setChildren(children);//定义直接被主管部门(集合)
        d1.setParent(d4);//定义直接主管部门
        Iterator it = children.iterator();//运用到了迭代遍历,四种之一!
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX阅读 870评论 0 1
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,598评论 18 399
  • 一、集合框架的概述 1、概述: 1、简述:所谓集合,就是为方便对多个对象的操作,对对象进行存储。集合就是存储对象最...
    玉圣阅读 508评论 0 4
  • 集合类简介 为什么出现集合类?面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就要对对象进...
    阿敏其人阅读 1,412评论 0 7
  • 一、【链表的创建】: 【1】、空链表: 【2】、头插法; 【3】、尾插法: 二、【链表的遍历和查找】: 链表的结构...
    遮天的龙阅读 1,810评论 6 18