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

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

一 集合的由来

需求1:20个学员。用Student描述,创建Student对象。

既然对象很多先进行存储---数组。

Student[] stus = new Student[20];

需求2:又来来了一个新学员。

原来的容器用不了。数组的长度是固定的。

解决:

创建一个新数组,将原来数组中的元素复制到新数组中。
麻烦。Java中提供解决问题的对象---->集合。

当数据多了需要存储,需要容器,而数据的个数不确定,无法使用数组,这时可以使用Java中另一个容器--集合。

集合和数组的区别?

数组的长度是固定的。
集合的长度是可变的。

数组中存储的是同一类型的元素,可以存储基本数据类型值。

集合存储的都是对象。而且对象的类型可以不一致。

什么时候使用集合呢?

当对象多的时候,先进行存储。

这些容器怎么区分?

区分的方式:每一个容器的数据结构不一样。

数据存储到的一种方式。

不断的向上抽取过程中,出现体现,形成了集合框架。

最顶层:Collection接口。
学习体系:看顶层,用底层。

了解顶层Collection:

一个容器:添加,删除,获取等功能。

Collection:

|--List:有序的,带索引的,通过索引就可以精确的操作集合中的元素,元素是可以重复的。
List提供了增删改查动作
增加add(element) add(index,element) ;
删除remove(element) remove(index);
修改set(index,element);
查询get(index);
|--Set:

//    演示Collection中带all方法 。    public static void collectionDemo2(Collection c1,Collection c2){                //1,给两个集合添加元素。        c1.add("abc1");        c1.add("abc2");        c1.add("abc3");                c2.add("abc1");        c2.add("abc4");        c2.add("abc5");                //添加所有c2的元素到c1中。//        c1.addAll(c2);        //        boolean b = c1.containsAll(c2);//        System.out.println("b="+b);                //删除c1中所有和c2相同的元素。//        c1.removeAll(c2);                //保留了c1中和c2相同的元素。        c1.retainAll(c2);                //打印。        System.out.println("c1="+c1);            }    //    演示Collection中常见的一般方法。    public static void collectionDemo(Collection coll) {                //1,往集合中添加对象元素。add(Object);        coll.add("itcast1");        coll.add("itcast2");        coll.add("itcast3");                        //2,删除。//        coll.remove("itcast2");                //3,判断是否包含。        System.out.println(coll.contains("itcast11"));                //4,清除。        coll.clear();        //把集合打印一下。        System.out.println(coll);//[itcast1, itcast2, itcast3]            }

1.1 集合框架图

 图1

 

 

 

 

1.2 集合的细节@

public static void main(String[] args) {                Collection coll = new ArrayList();                /*         * 细节。         * 1,集合中存储其实都是对象的地址。         * 2,集合中可以存储基本数值吗?不行,但是jdk1.5以后可以这么写,但是存储的还是对象(基本数据类型包装类对象)。         * 3,存储时提升了Object。取出时要使用元素的特有内容,必须向下转型。         */                //coll存储元素。//        coll.add("abc1");//存储的是对象的引用。        //        coll.add(3);//coll.add(Integer.valueOf(3));//自动装箱。                coll.add("itcast1");//Object obj = "itcast1";提升为了Object。        coll.add("hehe");//        coll.add("nba");                for (Iterator it = coll.iterator(); it.hasNext();) {                        Object object = it.next();//取出来的都是Object。需要使用元素的特有方法时需要向下转型。            String str = (String)object;            System.out.println(str.length());                    }    }

1.3  重复的概念equals

里面的重复是指的是引用是否重复,也就是equals方法来比较的,你也可以重写equals 方法。建立自己的比较方式

 重复都是有判断依据的,都是通过方法来完成的。

public boolean equals(Object obj) {        if(this == obj)            return true;        if(! (obj instanceof Student))            throw new RuntimeException("类型异常");        Student stu = (Student)obj;                return (this.name.equals(stu.name) && (this.age == stu.age));    }    public static void main(String[] args) {        Collection coll = new ArrayList();                Student stu = new Student(21,"lishi");        coll.add(stu);        coll.add(new Student(21,"lisi"));        for (Iterator iterator = coll.iterator(); iterator.hasNext();) {            Student  student = (Student) iterator.next();            System.out.println(student.toString());                    }

 

二 迭代@

也是集合的取出方式

public static void main(String[] args) {        /*         * 集合的取出方式。         *          * 迭代器是Collection集合中通用的取出方式。         *          */        //1,创建集合对象。        Collection coll = new ArrayList();        coll.add("abc1");        coll.add("abc2");        coll.add("abc3");        coll.add("abc4");                /*//2.获取容器的迭代器对象。通过iterator方法。        Iterator it = coll.iterator();                //3,使用具体的迭代器对象获取集合中的元素。参阅迭代器的方法        while(it.hasNext()){            System.out.println(it.next());        }*/                for (Iterator it = coll.iterator(); it.hasNext();) {            System.out.println(it.next());        }                //        System.out.println(it.next());//        System.out.println(it.next());//        System.out.println(it.next());//        System.out.println(it.next());//        System.out.println(it.next());//java.util.NoSuchElementException没有这个元素异常。    }}

三 ListIterator 

package cn.itcast.api.a.ListIterator;import java.util.ArrayList;import java.util.List;import java.util.ListIterator;public class ListIteratorDemo {    /**     * @param args     */    public static void main(String[] args) {                        List list = new ArrayList();                list.add("itcast1");        list.add("itcast2");        list.add("itcast3");        list.add("itcast4");                /*         *  获取集合中的元素。         *  如果集合中有元素等于 itcast2.那么就插入一个新的元素,java。         *           *  引发了java.util.ConcurrentModificationException         *  在迭代过程中,使用了集合的方法对元素进行操作。导致迭代器并不知道集合中的变化,容易引发数据的不确定性。         *           *  解决:在迭代时,不要使用集合的方法操作元素。         *  那么想要在迭代时对元素操作咋办?可以使用迭代器的方法操作。         *  可是很遗憾:迭代器的方式只有 hasNext() ,next(),remove();         *  Iterator有一个子接口ListIterator可以完成该问题的解决。如何获取该子接口对象呢?         *  通过List接口中的listIterator()就可以获取,         *  记住:该列表迭代器只有List接口有。而且这个迭代器可以完成在迭代过程中的增删改查动作。         *           *           *///        Iterator it = list.iterator();//        获取列表迭代其对象        ListIterator it = list.listIterator();                while(it.hasNext()){                        Object obj = it.next();            if("itcast2".equals(obj)){//                list.add("java");//                it.add("java");                it.set("java");            }        }                System.out.println(list);    }}

四 List

|--List:有序的,带索引的,通过索引就可以精确的操作集合中的元素,元素是可以重复的。

List提供了增删改查动作
增加add(element) add(index,element) ;
删除remove(element) remove(index);
修改set(index,element);
查询get(index);

|--Vector:可以增长的数组结构。同步的。效率非常低。已被ArrayList替代。

|--ArrayList:是数组结构,长度是可变的(原理是创建新数组+复制数组),查询速度很快,增删较慢,不同步的。
|--LinkedList:是链表结构,不同步的,增删速度很快,查询速度较慢。
可用于实现堆栈,队列。
堆栈:先进后出 First in Last Out FILO 手枪弹夹。
队列:先进先出 First in First Out FIFO 排队买票。
List可以存储重复元素的,如果需求中要求容器中的元素必须保证唯一性。

 

4.1 LinkedList

package cn.itcast.api.b.list.subclass;import java.util.LinkedList;public class LinkedListDemo {    /**     * @param args     */    public static void main(String[] args) {                /*         * LinkedList做个了解。         * 特有:围绕头和尾展开定义的。First Last。         * addFirst();         * addLast();         *          * getFirst();:获取头部元素。         * getLast();         *          * removeFirst();获取头部元素,并删除头部元素。         * removeLast();         */                LinkedList link = new LinkedList();                link.addFirst("abc1");        link.addFirst("abc2");        link.addFirst("abc3");        //        System.out.println(link.getFirst());//        System.out.println(link.getFirst());        //        System.out.println(link.removeFirst());//        System.out.println(link.removeFirst());//        System.out.println(link.removeFirst());//        System.out.println(link.removeFirst());                while(!link.isEmpty()){                        System.out.println(link.removeLast());        }                    }}

 

4.1.1 用LinkList模拟栈和队列

package cn.itcast.api.b.list.subclass;import java.util.LinkedList;public class LinkedListTest {    /**     * @param args     */    public static void main(String[] args) {        /*         * 面试题:用LinkedList模拟一个堆栈或者队列数据结构。         * 创建一个堆栈或者队列数据结构对象,该对象中使用LinkedList来完成的。         *          * 自定义堆栈结构。作业。         */        //创建一个队列对象。        Queue queue = new Queue();        //往队列中添加元素。        queue.myAdd("itcast1");        queue.myAdd("itcast2");        queue.myAdd("itcast3");        queue.myAdd("itcast4");                while(!queue.isNull()){            System.out.println(queue.myGet());        }    }}/** * 定义一个队列数据结构。Queue */class Queue{    //封装了一个链表数据结构。    private LinkedList link;    /*     * 队列初始化时,对链表对象初始化。     */    Queue(){        link = new LinkedList();    }        /**     * 队列的添加元素功能。     */    public void myAdd(Object obj){        //内部使用的就是链表的方法。        link.addFirst(obj);    }        /**     * 队列的获取方法。     */    public Object myGet(){        return link.removeLast();    }        /**     * 判断队列中元素是否空,没有元素就为true。     */    public boolean isNull(){        return link.isEmpty();    }}

 

4.1.2 去重复元素

4.2 equals

package cn.itcast.api.b.list.subclass;import java.util.ArrayList;import java.util.Iterator;import java.util.List;import cn.itcast.domain.Student;public class ArrayListTest {    /**     * @param args     */    public static void main(String[] args) {                List list = new ArrayList();//        list.add("abc1");//        list.add("abc2");//        list.add("abc1");//        list.add("abc2");//        list.add("abc1");//        list.add("abc2");                list.add(new Student("lisi1",21));        list.add(new Student("lisi2",22));        list.add(new Student("lisi1",21));        list.add(new Student("lisi2",22));        list.add(new Student("lisi1",21));                getSingleElement(list);//去除重复元素。                System.out.println(list);    }        /*     * 案例:去除List集合中的重复元素。     *      * 思路:     * 1,先创建一个临时容器。用于存储唯一性的元素。     * 2,遍历原容器,将遍历到的元素到临时容器中去判断,是否存在。     * 3,如果存在,不存储到临时容器,如果不存在,存储到临时容器中。     * 4,遍历结束后,临时容器中存储的就是唯一性的元素。     * 5,如果需要将这些唯一性的元素保留到原容器中,只要将原容器清空,将临时容器中的元素添加到原容器中即可。     *      */    public static void getSingleElement(List list){                //1,创建一个临时容器。        List temp = new ArrayList();                //2,遍历原容器。        for (Iterator it = list.iterator(); it.hasNext();) {            Object obj = it.next();                        //对遍历到的每一个元素都到临时容器中去判断是否包含。            if(!temp.contains(obj)){
//如果不存在, temp.add(obj);//添加到临时容器。 } } //唯一性的元素已经被记录到临时容器中。 //清空原容器中的元素。 list.clear(); //把临时容器中的元素添加到原容器中。 list.addAll(temp); }}

/**

* 重写了equals方法,建立Student对象判断相同的依据。
*/
@Override
public boolean equals(Object obj) {

 

System.out.println("equals");

if (this == obj)
return true;

 

if (!(obj instanceof Student)) {

throw new ClassCastException();
}

 

Student stu = (Student) obj;

return this.name.equals(stu.name) && this.age == stu.age;
}

 

 

 五 set

|--Set:不包含重复元素的集合,不保证顺序。而且方法和Collection一致。Set集合取出元素的方式只有一种:迭代器。

  |--HashSet:哈希表结构,不同步,保证元素唯一性的方式依赖于:hashCode(),equals()方法。查询速度快。
  |--TreeSet:可以对Set集合中的元素进行排序。使用的是二叉树结构。如何保证元素唯一性的呢?
使用的对象比较方法的结果是否为0,是0,视为相同元素不存。
元素的排序比较有两种方式:
1,元素自身具备自然排序,其实就是实现了Comparable接口重写了compareTo方法。
如果元素自身不具备自然排序,或者具备的自然排序不是所需要的,这时只能用第二种方式。
2,比较器排序,其实就是在创建TreeSet集合时,在构造函数中指定具体的比较方式。
需要定义一个类实现Comparator接口,重写compare方法。

5.1 HashSet

HashSet:哈希表结构,不同步,保证元素唯一性的方式依赖于:hashCode(),equals()方法。查询速度快。

注意:重点是哈希冲突是怎么解决的

5.2 重复元素去掉hashCode,equals

package cn.itcast.api.c.set;import java.util.HashSet;import java.util.Iterator;import java.util.Set;import cn.itcast.domain.Student;public class SetDemo {    /**     * @param args     */    public static void main(String[] args) {                Set set = new HashSet();                /*//        去除了字符串中的重复元素。        set.add("nba");        set.add("java");        set.add("haha");        set.add("itcast");        set.add("haha");        set.add("java");        set.add("java");        set.add("java");        set.add("itcast");*/                /*         *          * 为什么学生对象没有保证唯一性呢?         * 通过对哈希表的分析。         * 存储元素时,先调用了元素对象的hashCode()方法,而每个学生对象都是新建立的对象,         * 所以hashCode值都不相同,也就不需要判断equals了。         * 想要按照需求同姓名同年龄来保证学生对象的唯一性咋办?         * 不能使用Object中hashCode方法,需要重新定义hashCode的算法内容。         * 简单说:重写hashCode方法。         */        set.add(new Student("lisi1",21));        set.add(new Student("lisi2",22));        set.add(new Student("lisi1",21));        set.add(new Student("lisi2",22));        set.add(new Student("lisi1",21));                "abc1".hashCode();                for (Iterator it = set.iterator(); it.hasNext();) {            System.out.println(it.next());        }    }} 、
 

 

5.3 TreeSet

|--TreeSet:可以对Set集合中的元素进行排序。使用的是二叉树结构。如何保证元素唯一性的呢?

使用的对象比较方法的结果是否为0,是0,视为相同元素不存。
元素的排序比较有两种方式:
1,元素自身具备自然排序,其实就是实现了Comparable接口重写了compareTo方法。
如果元素自身不具备自然排序,或者具备的自然排序不是所需要的,这时只能用第二种方式。
2,比较器排序,其实就是在创建TreeSet集合时,在构造函数中指定具体的比较方式。
需要定义一个类实现Comparator接口,重写compare方法

Comparable和comparator 其实是一种策略模式

演示TreeSet

package cn.itcast.api.c.set;import java.util.Iterator;import java.util.Set;import java.util.TreeSet;import cn.itcast.domain.Student;public class TreeSetDemo {    /**     * @param args     */    public static void main(String[] args) {            //演示TreeSet,        Set set = new TreeSet();        /*        set.add("nba");        set.add("abc");        set.add("java");        set.add("aaa");        */        /*         * TreeSet的add方法内部最终实现:         * 需要将元素转成Comparable类型,为什么?因为这个类型具备排序的能力。         * 这个类型中有一个专门为排序提供了一个compareTo方法。         * 如果要让学生具备比较排序的功能,需要让学生扩展功能,实现Comparable接口。         */        set.add(new Student("lisi6",21));        set.add(new Student("lisi8",22));        set.add(new Student("lisi5",25));        set.add(new Student("lisi3",23));        set.add(new Student("lisi7",20));                                for (Iterator it = set.iterator(); it.hasNext();) {            System.out.println(it.next());        }    }} 如果不重写comparable里面的方法报的异常 重写之后

 

/*

* 注意:在比较时,必须明确主次。主要条件相同,继续比较次要条件。
*/
int temp = this.age - stu.age;
return temp==0?this.name.compareTo(stu.name):temp;

 

 TreeSet比较结构

 这里好像二叉排序树

 

TreeSet comparator

package cn.itcast.api.c.set;import java.util.Iterator;import java.util.Set;import java.util.TreeSet;import cn.itcast.api.d.comparator.ComparatorByName;import cn.itcast.domain.Student;public class TreeSetDemo2 {    /**     * @param args     */    public static void main(String[] args) {        //在创建TreeSet集合对象时明确比较器。        Set set = new TreeSet(new ComparatorByName());        /*         * 想要按照学生的姓名排序,说明学生中的自然排序不是所需要的。         * 这时只能使用比较器。ComparatorByName。         */        set.add(new Student("lisi6",21));        set.add(new Student("lisi8",22));        set.add(new Student("lisi5",25));        set.add(new Student("lisi3",23));        set.add(new Student("lisi7",20));                for (Iterator it = set.iterator(); it.hasNext();) {            System.out.println(it.next());        }    }}

 

 总结:

到此为止:再往集合中存储对象时,通常该对象都需要覆盖hashCode,equals,

同时实现Comparale接口,建立对象的自然排序。通常还有一个方法也会复写toString();

5.4 练习

package cn.itcast.api.c.set;import java.util.Collections;import java.util.Iterator;import java.util.Set;import java.util.TreeSet;import cn.itcast.api.d.comparator.ComparatorByLength;public class TreeSetTest {    /**     * @param args     */    public static void main(String[] args) {                /*         * 练习:要对字符串进行长度(由短到长)排序。         * 思路:         * 1,字符串之所以可以排序,因为是已经实现Comparable接口重写compareTo方法。         * 建立了字符串的自然排序。         * 2,但是自然排序不是需求中所需要的。咋办?         * 只能使用比较器。需要自定义一个比较器。         *          */        Set set = new TreeSet(Collections.reverseOrder(new ComparatorByLength()));                set.add("abc");        set.add("haha");        set.add("xixi");        set.add("z");        set.add("hiahia");                for (Iterator it = set.iterator(); it.hasNext();) {            System.out.println(it.next());        }    }}

5.5 LinkedHashSet

Hash查询快,但是查出来是没有顺序的。我想怎么存进去的,怎么取出来

这时要用到LinkedHashSet;

package cn.itcast.api.c.set;import java.util.Iterator;import java.util.LinkedHashSet;import java.util.Set;public class LinkedHashSetDemo {    /**     * @param args     */    public static void main(String[] args) {                        /*         * 提高唯一性元素的查询效率,还想有序,可使用HashSet的子类LinkedHashSet.         */        Set set = new LinkedHashSet();                set.add("abcd");        set.add("hahahah");        set.add("java");        set.add("itcast");                for (Iterator it = set.iterator(); it.hasNext();) {            System.out.println(it.next());        }    }}

 

5.6 foreach循环

package cn.itcast.api.e.foreach;import java.util.ArrayList;import java.util.List;public class ForeachDemo {    /**     * @param args     */    public static void main(String[] args) {                /*         * foreach:其实就是增强for循环。         * 格式:         * for(元素的数据类型  变量   : Collection集合or数组){}         * 用于遍历Collection和数组。通常只能遍历元素,不要在遍历的过程中做对集合元素的操作。         *          * 和老式的for循环有什么区别?         * 注意:新for循环必须有被遍历的目标。目标只能是Collection或者是数组。         * 建议:遍历数组时,如果仅为遍历,可以使用增强for如果要对数组的元素进行 操作,使用老式for循环可以通过角标操作。         *          */                List list = new ArrayList();        list.add("itcast1");        list.add("itcast2");        list.add("itcast3");        list.add("itcast4");        //        for (Iterator it = list.iterator(); it.hasNext();) {//            Object obj = it.next();//            System.out.println(obj);//        }                for(Object obj : list){
//简化。 System.out.println(obj); } }}

 

5.7 查阅的小技巧

看集合对象的小技巧:★★★★★★

集合分体系。List Set
子类对象的后缀名是所属体系,前缀名是数据结构名称。
List:新出的子类都是以List结尾的,通常都是非同步的。
|--ArrayList :看到array,就知道数组,查询速度快。
|--LinkedList:看到link,就知道链表,增删速度快。
Set:
|--HashSet:看到hash,就知道哈希表,查询速度更快,并想到元素唯一,通过hashCode(),equals方法保证唯一性。
|--TreeSet:看到tree,就知道二叉树,可以排序,排序想到Comparable-compareTo Comparator--compare方法。

 

转载于:https://www.cnblogs.com/liu-wang/p/8290359.html

你可能感兴趣的文章
阶段3 2.Spring_03.Spring的 IOC 和 DI_6 spring中bean的细节之三种创建Bean对象的方式
查看>>
阶段3 2.Spring_04.Spring的常用注解_3 用于创建的Component注解
查看>>
阶段3 2.Spring_04.Spring的常用注解_2 常用IOC注解按照作用分类
查看>>
阶段3 2.Spring_09.JdbcTemplate的基本使用_5 JdbcTemplate在spring的ioc中使用
查看>>
阶段3 3.SpringMVC·_07.SSM整合案例_02.ssm整合之搭建环境
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_3、快速创建SpringBoot应用之手工创建web应用...
查看>>
阶段3 3.SpringMVC·_07.SSM整合案例_04.ssm整合之编写SpringMVC框架
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第1节零基础快速入门SpringBoot2.0_5、SpringBoot2.x的依赖默认Maven版本...
查看>>
阶段3 3.SpringMVC·_07.SSM整合案例_08.ssm整合之Spring整合MyBatis框架
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_9、SpringBoot基础HTTP其他提交方法请求实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第2节 SpringBoot接口Http协议开发实战_12、SpringBoot2.x文件上传实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_19、SpringBoot个性化启动banner设置debug日志...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_20、SpringBoot2.x配置全局异常实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第5节 SpringBoot部署war项目到tomcat9和启动原理讲解_23、SpringBoot2.x启动原理概述...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第4节 Springboot2.0单元测试进阶实战和自定义异常处理_21、SpringBoot2.x配置全局异常返回自定义页面...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第8节 数据库操作之整合Mybaties和事务讲解_32..SpringBoot2.x持久化数据方式介绍...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第8节 数据库操作之整合Mybaties和事务讲解_34、SpringBoot整合Mybatis实操和打印SQL语句...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第8节 数据库操作之整合Mybaties和事务讲解_35、事务介绍和常见的隔离级别,传播行为...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_40、Redis工具类封装讲解和实战...
查看>>
小D课堂 - 零基础入门SpringBoot2.X到实战_第9节 SpringBoot2.x整合Redis实战_37、分布式缓存Redis介绍...
查看>>