集合框架(一)

一,概述

1.集合体系结构:单例集合,双列集合

collection代表单列集合,每个元素(数据)只包含一个值;

Map代表双列集合,每个元素包含两个值(键值对)

2.Collection集合体系

(1)List系列集合:添加的元素是有序,可重复有,有索引

ArrayList,LinekdList:有序,可重复,有索引

(2)Set系列集合:添加的元素是无序,不重复,无索引

HashSet:无序,不重复,无索引

LinkedHashSet:有序,不重复,无索引

TreeSet:按照大小默认升序排序,不重复,无索引

二,Collection的常用方法

1.collection是单列集合的祖宗,它规定的方法是全部单列集合都会继承的

        Collection<String> c=new ArrayList<>();
        //1.public void add(E e);添加
        c.add("java1");
        c.add("java1");
        c.add("java2");
        c.add("java2");
        c.add("java3");
        System.out.println(c);//会自动调用toString方法打出的是内容[java1,java1,java2,java2,java3]
        //2.public void clear():清空集合的元素
        //c.clear();
        System.out.println(c);//[]
        //3.public boolean isEmpty():判断集合是否为空 是空返回true,反之
        System.out.println(c.isEmpty());
        //4.public int size():获取集合的大小
        System.out.println(c.size());//5
        //5.public boolean contains(Object obj):判断集合中是否包含某个元素
        System.out.println(c.contains("java1"));//true
        //6.public boolean remove(E e):删除某个元素,如果有多个重复元素默认删除最前面一个
        System.out.println(c.remove("java1"));//true
        System.out.println(c);//[java1,java2,java2,java3]
        //7.public Object[] toArray():把集合换成数组
        Object[] arr=c.toArray();
        System.out.println(Arrays.toString(arr));//[java1,java2,java2,java3]

        String[] arr2=c.toArray(new String[c.size()]);
        System.out.println(Arrays.toString(arr2));//[java1,java2,java2,java3]
        System.out.println("------------");
        //把一个集合的全部数据倒入到另一个集合中去
        Collection<String> c1=new ArrayList<>();
        c1.add("java1");
        c1.add("java2");
        Collection<String> c2=new ArrayList<>();
        c2.add("java3");
        c2.add("java4");
        c1.addAll(c2);//就是把c2集合里面的数据全部倒入c1集合中去(c1与c2数据类型相同)
        System.out.println(c);//[java1,java2,java3,java4]

三,Collection的遍历方式

迭代器

1.概述:迭代器是用来遍历集合的专用方式(数组没有迭代器0,在Java中迭代器的代表是Iterator

2.Collection集合获取迭代器的方法

Iterator<E> iterator()    返回集合中的迭代器对象,该迭代器对象默认指向当前集合的第一个元素

3.Iterator迭代器中的常用方法

boolean hasNext()     询问当前位置是否有元素存在,存在返回true,不存在返回false

E next()     获取当前位置的元素,并同时将迭代器对象指向下一个元素处

        Collection<String> c=new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("素素");
        c.add("灭绝");
        Iterator<String> it = c.iterator();
       // System.out.println(it.next());
//次数不能超过会出现异常
//2.我们应该使用循环结合迭代遍历集合
        while (it.hasNext()){
            String ele=it.next();
            System.out.println(ele);
        }

 增强for循环

格式:for(元素的数据类型:数组或者集合){}

1.增强for可以用来遍历集合或者数组

2.增强for遍历集合,本质就是迭代器遍历集合的简化写法

 Collection<String> c=new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("素素");
        c.add("灭绝");
        System.out.println(c);
        //使用增强for遍历集合或者数组
        for(String ele:c){
            System.out.println(ele);
        }
        String[] names={"迪丽热巴","古力娜扎","稀奇哈哈"};
        for (String name:names){
            System.out.println(name);
        }

Lambda表达式

1.Lambda表达式遍历集合

得益于JDK8开始的新技术Lambda表达式,提供了一种更简单,更直接的方式来比遍历集合

2.需要使用Collection的如下方法来完成

default void forEach(Consumer<? super T> action)      结合Lambda遍历集合

 Collection<String> c=new ArrayList<>();
        c.add("赵敏");
        c.add("小昭");
        c.add("素素");
        c.add("周若至");
        System.out.println(c);
        //default void forEach(Consumer<? super T> action):结合Lambda表达式遍历集合
        //Consumer是个接口不能直接创建对象,用匿名内部类
        c.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
       // c.forEach(s->System.out.println(s));//简写
    }

 四,List集合

特点,特有方法

1.List系列集合特点:有序,重复,有索引

2.List集合的特有方法

list集合因为支持索引,所以多了很多与索引相关的方法,Collection的功能list也继承了

 //1.创建一个ArrayList集合对象(有序,可重复,有索引)
        List<String> List=new ArrayList<>();//LinkedList<>();
        List.add("蜘蛛精");
        List.add("至尊宝");
        List.add("至尊宝");
        List.add("牛夫人");
        System.out.println(List);
        //2.public void add(int index,E element):在某个索引位置插入元素
        List.add(2,"紫霞仙子");
        System.out.println(List);
        //3.public E remove(int index):根据索引删除元素,返回被删除的元素
        System.out.println(List.remove(2));//紫霞仙子
        System.out.println(List);
        //4.public E get(int index):返回集合中指定位置处的元素
        System.out.println(List.get(3));
        //5.public E set(int index,E element):修改索引位置处的元素,修改成功后,会返回原来的数据
        System.out.println(List.set(3,"牛魔王"));//牛夫人

遍历方式

1.List集合支持的遍历方式

(1)for循环(因为List集合有索引)

(2)迭代器

(3)增加for循环

(4)Lambda表达式

  List<String> list=new ArrayList<>();
        list.add("糖宝宝");
        list.add("蜘蛛精");
        list.add("至尊宝");
        //1.for循环
        for (int i=0;i<list.size();i++){
            String s= list.get(i);
            System.out.println(s);
        }
        //2.迭代器
        Iterator<String> it= list.listIterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        //3.增强for循环(foreach遍历)
        for (String s : list) {
            System.out.println(s);
        }
        //4.JDK 1.8开始之后的Lambda表达式
        list.forEach(s->{
            System.out.println(s);
        });

ArrayList集合的底层原理

1.基于数组实现的

2.查询速度快(注意:是根据索引查询数据快):查询数据通过地址值和索引定位,查询任意数据耗时相同

3.删除效率低:可能更需要把后面很多的数据进行前移

4.添加效率极低:可能需要把后面很多的数据后移,再添加元素;或者也可能需要进行数组的扩容

查询快,增删慢

5.(1)利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组

(2)添加第一个元素时,底层会创建一个新的长度为10的数组

(3)存满时,会扩容1.5倍

(4)如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准

 LinkedList集合的底层逻辑

基于双链表实现的

1.什么是链表?特点?

链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址

下一个结点的地址

----------->

下一个结点的地址

 

(1)链表的特点一:查询慢,无论查询哪个数据都要从头开始找

(2)链表的特点二:链表的增删相对快

2.单向列表,双向列表

双向列表特点:查询慢,增删相对比较快,但对首尾元素进行增删改查速度是极快的

3.LinkedList新增了很多首尾操作的方法

public void addFirst(E e)   在该列表开头插入指定的元素

public void addLast(E e)    将指定的元素追加到此列表的末尾

public E getFirst()    返回此列表中的第一个元素

public E getLast()     返回此列表中的最后一个元素

public E removeFirst()     从此列表中删除并返回第一个元素

public E removeLast()     从此列表中删除并返回最后一个元素

4.应用场景

//1.创建一个队列
        LinkedList<String> queue=new LinkedList<>();
        //入列
        queue.addLast("第一号人");
        queue.addLast("第二号人");
        queue.addLast("第三号人");
        queue.addLast("第四号人");
        //出列
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue.removeFirst());
        System.out.println(queue);
        System.out.println("-----------------------");
        //2.创建一个栈对象
//后进先出,先进后出
        LinkedList<String> stack=new LinkedList<>();
        //压线(push)
        stack.addFirst("第一个子弹");
        stack.addFirst("第二个子弹");
        stack.addFirst("第三个子弹");
        stack.push("第四个子弹");//push与addFirst一样
        //出栈(pop)
        System.out.println(stack.removeFirst());
        System.out.println(stack.pop());
        System.out.println(stack);

五,Set集合

特点

1.Set系列集合特点:无序:添加数据的顺序和获取出的数据顺序不一致;不重复,无索引;

(1)HashSet:无序,不重复,无索引

(2)LinkedHashSet:有序,不重复,无索引

(3)TreeSet:排序,不重复,无索引

注意:Set要用到的常用方法,基本上就是Collection提供的,自己几乎没有额外一些常用功能

HashSet集合的底层原理

哈希值

(1)就是一个int类型的数据,Java中每个对象都有一个哈希值

(2)Java中所有对象,都可以调用Object类提供的hashCode方法,返回该对象自己的哈希值public int hashCode():返回对象的哈希值

哈希值的特点

(1)同一个对象多次调用hashCode()方法返回的哈希值是相同的

(2)不同的对象,它们的哈希值一般不同,但也可能相同(哈希碰撞)

1.HashSet集合的底层原理

(1)基于哈希表实现

(2)哈希表是一种增删改查数据,性能都比较好的数据结构

2.哈希表

(1)JDK8之前,哈希表=数组+链表

创建一个默认长度为16的数组,默认加载因子为0.75,数组名table

使用元素的哈希值对数组的长度求余计算出存入的位置

判断当前位置是否为null,如果是null直接存入

如果不为null,表示有元素,则调用equals方法比较,相等,则不存

(JDK8之前,新元素存入数组,占老元素位置,老元素挂下面;JDK8开始,新元素直接挂在老元素下面)

如果数组快占满了,链表会过长,导致查询性能降低(扩容)

 

(2)JDK8开始,哈希表=数组+链表+红黑树

红黑树进一步提高了操作数据的性能

结论:如果希望Set集合认为2个内容一样的对象是重复的,必须重写对象的Hash Code()和equals()方法

LinkedHashSet集合的底层原理

 1.原理

(1)依然是基于哈希表(数组,链表,红黑树)实现的

(2)但是,它的每个元素都额外的多了一个双链表记录它前后元素的位置

TreeSet

1.特点:不重复,无索引,可排序(默认升序排序,按照元素的大小,由小到大排序)

2。基层是基于红黑树实现的排序

注意:

(1)对于数组类型:Integer,Double,默认按照数据本身的大小进行升序排序

(2)对于字符串类型:默认按照首字符的编号升序排序

(3)对于自定义类型如Student对象,TreeSet默认是无法直接排序的

方法一:让自定义的类实现Comparable接口,重写方法

方法二:通过调用TreeSet集合的有参数构造器,可以设置Comparable对象(比较对象)

六,集合的并发修改异常

 1.集合的并发修改异常

(1)使用迭代器遍历集合时,有同事在删除集合中的数据,程序就会出现并发修改异常的错误

(2)由于增强for循环遍历集合就是迭代器集合的简化写法,因此,使用增加for循环遍历集合,又在删除集合中的数据时,程序也会出现并发修改异常的错误

2.怎么保证遍历集合同时删除时不出现bug?

(1)使用迭代器遍历集合,但是迭代器自己的删除方法删除数据即可

(2)如果能用for循环遍历时,可以倒着遍历并删除,或者从前往后遍历,但删除元素后做i--操作

 

 

  • 24
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值