基础复习第十八天   集合框架的使用和源码分析

集合

集合的概述和总结

集合是java中提供的一种容器,可以用来存储多个数据。

集合和数组既然都是容器,它们有啥区别呢?

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

  • 数组中可以存储基本数据类型值,也可以存储对象,而集合中只能存储对象

集合主要分为两大系列:Collection和Map,Collection 表示一组对象,Map表示一组映射关系或键值对。

一·集合框架的概述

<p>

1.集合,数组都是对多个数据进行存储操作的结构,简称java容器。

说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中的数据等)。

2.1数组在存储多个数据方面的特点:

> 一旦初始化以后,其长度就确定了。

>数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。

比如:String[] arr;int[] arr1;Object[] arr2;

2.2数组在存储多个数据方面的缺点:

>一旦初始化以后,其长度就不可修改。

>数组中提供的方法非常有限,对于添加、删除、插入数据等操作,非常的不方便,同时效率不高。

>获取数组中实际元素的个数的需求,数组没有现成的属性或者方法可用。

>数组存储数据的特点:有序,可重复。对于无序、不可重复的需求,不能满足。

<p>

二.集合框架

|---Collection接口:单列集合,用来存储一个一个的对象。

|---List接口:存储有序的、可重复的数据。也可以称为--->"动态数组"。

|---ArrayList、LinkedList、Vector。

|---Set接口:存储无序的、不可重复的数据。

|---HashSet、LinkedHashSet、TreeSet。

<p>

|---Map接口:双列集合,用来存储一对(key-value)一对的数据。

|---HashMap、LinkedHashMap、TreeMap、HashTable、Properties

Collection中抽象方法的使用(15个)

Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。JDK 不提供此接口的任何直接实现:它提供更具体的子接口(如 Set 和 List、Queue)实现。此接口通常用来传递 collection,并在需要最大普遍性的地方操作这些 collection。

结论:
  1. Collection接口的实现类的对象中添加数据o时,要求o所在类要重写equals()。

  1. ArrayList的equals和hashcode都进行了重写,并且hashcode的默认值为1。

Collection<E>是所有单列集合的父接口,因此在Collection中定义了单列集合(List和Set)通用的一些方法,这些方法可用于操作所有的单列集合。方法如下:

  1. boolean add(E e):将元素e,添加到集合col中。null也能存储成功,并且元素可以重复。 E是泛型,这里由于之前学的泛型忘了,还没复习到泛型;所以泛型统一用Object类型表示。
  1. int size():获取该集合中的元素个数。返回此集合中的元素数。如果此集合包含超过Integer。MAX_VALUE元素返回Integer.MAX_VALUE。
  1. boolean addAll(Collection<? extends E> c):将指定集合中的所有元素添加到此集合(可选操作)。如果在操作进行时修改了指定的集合, 则此操作的行为是未定义的。(这意味着如果指定的集合为此集合,且此集合非空,则此调用的行为是未定义的。)
  1. boolean isEmpty():判断当前集合是否为空,如果此集合不包含任何元素,则为 true。如果是放的null,结果返回false。因为null也是一个元素。
  1. public void clear():从此集合中移除所有元素(可选操作)。该方法返回后,集合将为空。
//Collection接口中的所有抽象方法的使用(15个),抽象方法是没有方法体的。
        Collection col = new ArrayList();

        //1.boolean add(E e):将元素e,添加到集合col中。null也能存储成功,并且元素可以重复。
        // E是泛型,这里由于之前学的泛型忘了,还没复习到泛型;所以泛型统一用Object类型表示。
        boolean aa = col.add("aa");
        System.out.println(aa);//true
        boolean add = col.add(null);
        boolean ad = col.add(null);
        System.out.println(add);//true
        col.add("bb");
        col.add("aa");
        col.add(123);//自动装箱:基本数据转化为包装类在使用。因为集合中不能存储基本数据类型的数据。
        col.add(new Date());
        System.out.println(col);//[aa, bb, aa, 123, Fri Feb 17 15:56:47 CST 2023]

        //2.int size():获取该集合中的元素个数。返回此集合中的元素数。如果此集合包含超过Integer。MAX_VALUE元素返回Integer.MAX_VALUE
        System.out.println(col.size());//7

        //3.boolean addAll(Collection<? extends E> c):将指定集合中的所有元素添加到此集合(可选操作)。如果在操作进行时修改了指定的集合,
        // 则此操作的行为是未定义的。(这意味着如果指定的集合为此集合,且此集合非空,则此调用的行为是未定义的。)
        //新建一个集合
        Collection col1 = new ArrayList();
        System.out.println(col1);//[]
        col.addAll(col1);
        System.out.println(col.size());//7
     col1.add(null);
        col1.add(34);
        col1.add(35);
        //将col1集合中的所有元素添加到col集合中
         col.addAll(col1);
        System.out.println(col.size());//10

        //4.boolean isEmpty():判断当前集合是否为空,如果此集合不包含任何元素,则为 true。如果是放的null,结果返回false。
        // 因为null也是一个元素。
        System.out.println(col1.isEmpty());//判断当前集合中的元素个数是否为0个

        //5.public void clear():从此集合中移除所有元素(可选操作)。该方法返回后,集合将为空。
        System.out.println(col1.size());//3
        System.out.println(col1.isEmpty());//false
        col1.clear();
        System.out.println(col1.size());//0
        System.out.println(col1.isEmpty());//true
  1. boolean contains(Object o):判断当前集合中是否包含o
  1. boolean containsAll(Object o):判断形参o中的所有元素是否都存在于当前集合中。
  /**
     * Collection接口中声明的方法的测试
     *结论: Collection接口的实现类的对象中添加数据o时,要求o所在类要重写equals()。
     */
    @Test
    public void test2() {

        Collection col = new ArrayList();
        col.add(123);
        col.add("欣爱康");
        col.add("fhakl");
        col.add(76532);
        //6.boolean contains(Object o):判断当前集合中是否包含o
        //我们在判断时会调用o对象所在类的equals()。
//        boolean contains = col.contains(123);
//        System.out.println(contains);//true
        //7.boolean containsAll(Object o):判断形参o中的所有元素是否都存在于当前集合中。
        Collection col1 = Arrays.asList(123, 4567);
        System.out.println(col.containsAll(col1));//false
        Collection col2 = Arrays.asList(123, 76532);
        System.out.println(col.containsAll(col2));//true
    }
  1. boolean remove(Object o):从当前集合中移除o元素。如果集合中有多个该元素只移除索引最小的那一个元素。
  1. boolean removeAll(Collection<?> c):从当前集合中移除与c集合共有的所有元素。
@Test
    public void test3() {
        Collection col = new ArrayList();
        col.add(123);
        col.add("欣爱康");
        col.add(123);
        col.add(123);
        col.add("欣爱康");
        col.add("fhakl");
        col.add(76532);
        //8.boolean remove(Object o):从当前集合中移除o元素。如果集合中有多个该元素只移除索引最小的那一个元素。
//        System.out.println(col.size());
//        System.out.println(col);
//        col.remove("欣爱康");
//        System.out.println(col.size());
//        System.out.println(col);

        //9.boolean removeAll(Collection<?> c):从当前集合中移除与c集合共有的所有元素。
        Collection col1 = new ArrayList();
        col1.add("欣爱康");
        col1.add("fhakl");
        col1.add(76);
        System.out.println(col.size());//7
        System.out.println(col);//[123, 欣爱康, 123, 123, 欣爱康, fhakl, 76532]
        System.out.println(col1.size());//3
        System.out.println(col1);//[欣爱康, fhakl, 76]
        col.removeAll(col1);
        System.out.println(col.size());//4
        System.out.println(col);//[123, 123, 123, 76532]
        System.out.println(col1.size());//3
        System.out.println(col1);//[欣爱康, fhakl, 76]

    }
  1. boolean retainAll(Collection<?> c):交集,获取当前集合与c集合的交集部分,并返回给当前集合。
 @Test
    public void test4() {
        Collection col = new ArrayList();
        col.add(123);
        col.add("欣爱康");
        col.add("欣爱康");
        col.add("欣爱康");
        col.add(123);
        //10.boolean retainAll(Collection<?> c):交集,获取当前集合与c集合的交集部分,并返回给当前集合。
        Collection col1 = new ArrayList();
        col1.add("欣爱康");
        col1.add("欣爱康");
        col1.add("fhakl");
        col1.add(76);
        System.out.println(col.size());//5
        System.out.println(col);//[123, 欣爱康, 欣爱康, 欣爱康, 123]
        System.out.println(col1.size());//4
        System.out.println(col1);//[欣爱康, 欣爱康, fhakl, 76]
        col.retainAll(col1);
        System.out.println(col.size());//3
        System.out.println(col);//[欣爱康, 欣爱康, 欣爱康]
        System.out.println(col1.size());//4
        System.out.println(col1);//[欣爱康, 欣爱康, fhakl, 76]




    }
  1. boolean equals(Object o):当前集合与o集合比较,如果每个索引位置的对象内容都相等才返回true,否则返回false。
 @Test
    public void test5() {
        Collection col = new ArrayList();
        col.add(123);
        col.add("欣爱康");
        //11.boolean equals(Object o):当前集合与o集合比较,如果每个索引位置的对象内容都相等才返回true,否则返回false。
        Collection col1 = new ArrayList();
        col1.add("欣爱康");
        col1.add(123);
        System.out.println(col.equals(col1));//false 因为ArrayList是有序可重复的。
        Collection col2 = new ArrayList();
        col2.add(123);
        col2.add("欣爱康");
        System.out.println(col.equals(col2));//true
    }
  1. hashCode():返回此集合的哈希码值。
如果equals方法被重写,hashCode方法一定要重写。两个对象比较时调用equals(Object o)返回true,那么两个对象的hashCode一定相等。两个对象的hashCode相等,两个对象不一定相等。
@Test
    public void test6() {
        Collection col = new ArrayList();
        System.out.println(new Object().hashCode());
        Collection col1 = new ArrayList();
        System.out.println(new ArrayList().hashCode());
        //12.hashCode():返回此集合的哈希码值。如果equals方法被重写,hashCode方法一定要重写。
        // 两个对象比较时调用equals(Object o)返回true,那么两个对象的hashCode一定相等。
        // 两个对象的hashCode相等,两个对象不一定相等。
        System.out.println(col.hashCode());
        System.out.println(col1.hashCode());
    }
  1. Object[] toArray():将当前集合转为数组。
  1. public static <T> List<T> asList(T... a):参数为可变形参,将当前数组转为集合。
  @Test
    public void test7() {
        //13.Object[] toArray():将当前集合转为数组。
        Collection col = new ArrayList();
        col.add(123);
        col.add("欣爱康");
        Object[] objects = col.toArray();
        System.out.println(col);//[123, 欣爱康]
        System.out.println(objects);//[Ljava.lang.Object;@c81cdd1
        System.out.println(new ArrayList());//[]
        System.out.println(new ArrayList().toArray());//[Ljava.lang.Object;@1fc2b765
        //14.public static <T> List<T> asList(T... a):参数为可变形参,将当前数组转为集合。
        List<Object> objects1 = Arrays.asList(objects);
        System.out.println(objects1);//[123, 欣爱康]
    }

Iterator迭代器:作用是遍历集合,跟for循环类似。本身并不是容器。

总结:集合元素的遍历操作,使用Iterator接口。
①通过迭代器遍历集合中的元素,每个元素只能被遍历一次,在一个方法中如果重复遍历,则可能会报java.util.NoSuchElementException的异常。
②如果集合中的元素是集合,那么通过迭代器遍历时输出的是内部的集合;
如果集合中的元素是数组,那么通过迭代器遍历该集合时输出的是这个数组的地址值。
③集合对象每次调用iterator()方法都得到一个新的迭代器对象,默认游标都在集合的第一个元素之前。
④内部定义了remove(),可以在遍历的时候,删除集合中的元素。此方法不同于集合直接调用remove().
⑤如果还未调用next()或在上一次调用next方法之后已经调用了remove方法,再调用remove都会报java.lang.IllegalStateException。
  1. hasNext():通过指针判断该集合中是否还有下一个元素,指针的初始位置在该集合第一个元素所在位置的前面。

  1. next():①指针下移②将下移以后集合位置上的元素返回。

 /**
     * 总结:集合元素的遍历操作,使用Iterator接口。
     * ①通过迭代器遍历集合中的元素,每个元素只能被遍历一次,在一个方法中如果重复遍历,则可能会报java.util.NoSuchElementException的异常。
     * ②如果集合中的元素是集合,那么通过迭代器遍历时输出的是内部的集合;
     * 如果集合中的元素是数组,那么通过迭代器遍历该集合时输出的是这个数组的地址值。
     * ③集合对象每次调用iterator()方法都得到一个新的迭代器对象,默认游标都在集合的第一个元素之前。
     */
    @Test
    public void test8() {

        //Iterator<E> iterator():返回此集合中元素的迭代器。对于元素的返回顺序没有保证(除非此集合是提供保证的某个类的实例)。
        //<E> –此集合中元素的类型
        String[] strings1 = new String[]{"太难1", "阿辉1", "法本记录卡1"};
        ArrayList list = new ArrayList();
        list.add("太难2");
        list.add("阿辉2");
        list.add("法本记录卡2");
        String[] strings2 = new String[]{"法拉克", "fabj", "法录卡"};
        ArrayList list1 = new ArrayList();
        list1.add("法拉克2");
        list1.add("fabj2");
        list1.add("法录卡2");
        Collection col = new ArrayList();
        col.add(strings1);
        col.add(strings2);
        col.add(list);
        col.add(list1);
        col.add(123);
        col.add("欣爱康");
        //迭代器:专门用来遍历集合。本身并不是容器
        Iterator iterator = col.iterator();

        //方式一:(不推荐)
//        System.out.println(iterator.next());//[Ljava.lang.String;@c81cdd1
//        System.out.println(iterator.next());//[Ljava.lang.String;@c81cdd1
//        System.out.println(iterator.next());//[太难2, 阿辉2, 法本记录卡2]
//        System.out.println(iterator.next());//[法拉克2, fabj2, 法录卡2]

        //方式二:(不推荐)
//        for (int i = 0; i < col.size(); i++) {
//            System.out.println(iterator.next());
//        }

        //方式三:(推荐)
        //hasNext():通过指针判断该集合中是否还有下一个元素,指针的初始位置在该集合第一个元素所在位置的前面。
        while (iterator.hasNext()) {
            //next():①指针下移②将下移以后集合位置上的元素返回。
            //123
            //欣爱康
            System.out.println(iterator.next());
        }

        //java.util.NoSuchElementException:由各种访问器方法引发,以指示所请求的元素不存在。
//        System.out.println(iterator.next());


    }
  @Test
    public void test9() {
        //Iterator<E> iterator():返回此集合中元素的迭代器。对于元素的返回顺序没有保证(除非此集合是提供保证的某个类的实例)。
        //<E> –此集合中元素的类型
        String[] strings1 = new String[]{"太难1", "阿辉1", "法本记录卡1"};
        ArrayList list = new ArrayList();
        list.add("太难2");
        list.add("阿辉2");
        list.add("法本记录卡2");

        Collection col = new ArrayList();
        col.add(strings1);
        col.add(list);
        col.add(123);
        col.add("欣爱康");
        //迭代器:专门用来遍历集合。本身并不是容器
        Iterator iterator = col.iterator();

        //错误的遍历:方式一
        //java.util.NoSuchElementException
//        while (iterator.next() != null) {
//            System.out.println(iterator.next());
//        }

        //错误的遍历:方式二
        while (col.iterator().hasNext()) {
            System.out.println(col.iterator().next());
        }
    }

java.util.Iterator接口

在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口java.util.Iterator。Iterator接口也是Java集合中的一员,但它与Collection、Map接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。

想要遍历Collection集合,那么就要获取该集合迭代器完成迭代操作,下面介绍一下获取迭代器的方法:

  • public Iterator iterator(): 获取集合对应的迭代器,用来遍历集合中的元素的。

下面介绍一下迭代的概念:

  • 迭代:即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续在判断,如果还有就再取出出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。

Iterator接口的常用方法如下:

  • public E next():返回迭代的下一个元素。

  • public boolean hasNext():如果仍有元素可以迭代,则返回 true。

迭代器的实现原理

当遍历集合时,首先通过调用集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。

Iterator迭代器对象在遍历集合时,内部采用指针的方式来跟踪集合中的元素,Iterator对象迭代元素的过程:

在调用Iterator的next方法之前,迭代器的索引位于第一个元素之前,指向第一个元素,当第一次调用迭代器的next方法时,返回第一个元素,然后迭代器的索引会向后移动一位,指向第二个元素,当再次调用next方法时,返回第二个元素,然后迭代器的索引会再向后移动一位,指向第三个元素,依此类推,直到hasNext方法返回false,表示到达了集合的末尾,终止对元素的遍历。

使用Iterator迭代器删除元素

/**
     * 通过迭代器中删除元素
     */
    @Test
    public void test10() {
        //
        ArrayList list = new ArrayList();
        list.add("太难2");
        list.add("阿辉2");
        list.add("法本记录卡2");
        Collection col = new ArrayList();
        col.add(list);
        col.add(123);
        col.add("欣爱康");
//        boolean remove = col.remove(123);//这是调用col对象里面的remove方法
//        System.out.println(col);
        Iterator iterator = col.iterator();
        //报异常:java.lang.IllegalStateException
        // iterator.remove();//这是调用的Iterator迭代器里面的remove方法
        //System.out.println(col);

        //删除集合中的指定元素
        while (iterator.hasNext()) {
            //①移动指针②将指针移动后所指的集合中的元素返回
            Object next = iterator.next();
            if ("欣爱康".equals(next)) {
                //调用迭代器的remove方法
                iterator.remove();

            }

        }
        System.out.println(iterator.hasNext());//false
        iterator = col.iterator();//将迭代器指针重置到初始位置
//        //重新遍历集合
        while (iterator.hasNext()) {
            System.out.print(iterator.next());//[太难2, 阿辉2, 法本记录卡2]123
        }


        // 通过指针判断该集合中是否还有下一个元素,如果有返回true
        while (iterator.hasNext()) {
            //调用迭代器的remove方法
            iterator.remove();//java.lang.IllegalStateException
        }
注意:不要在使用Iterator迭代器进行迭代时,调用Collection的remove(xx)方法,否则会报异常java.util.ConcurrentModificationException,或出现不确定行为。

增强for

增强for循环(也称for each循环)是JDK1.5以后出来的一个高级for循环,专门用来遍历数组和集合的。

格式:

for(遍历出来的元素的数据类型  变量名 : Collection集合or数组){ 
      //写操作代码
}
增强for循环内部仍然是调用迭代器进行遍历
遍历数组

通常只进行遍历元素,不要在遍历的过程中对数组元素进行修改

public class NBForDemo1 {
    public static void main(String[] args) {
        int[] arr = {3,5,6,87};
           //使用增强for遍历数组
        for(int a : arr){//a代表数组中的每个元素
            System.out.println(a);
        }
    }
}
遍历集合

通常只进行遍历元素,不要在遍历的过程中对集合中的元素进行增加、删除、替换操作

public class NBFor {
    public static void main(String[] args) {        
        Collection<String> coll = new ArrayList<String>();
        coll.add("小河神");
        coll.add("老河神");
        coll.add("神婆");
        //使用增强for遍历
        for(String s :coll){//接收变量s代表被遍历到的集合元素
            System.out.println(s);
        }
    }
}

java.lang.Iterable接口

java.lang.Iterable接口,实现这个接口允许对象成为 "foreach" 语句的目标。

Java 5时Collection接口继承了java.lang.Iterable接口,因此Collection系列的集合就可以直接使用foreach循环遍历。

java.lang.Iterable接口的抽象方法:

  • public Iterator iterator(): 获取对应的迭代器,用来遍历数组或集合中的元素的。

自定义某容器类型,实现java.lang.Iterable接口,发现就可以使用foreach进行迭代。

public class TestMyArrayList {
    public static void main(String[] args) {
        MyArrayList<String> my = new MyArrayList<>();
        for(String obj : my) {
            System.out.println(obj);
        }
    }
}
class MyArrayList<T> implements Iterable<T>{

    @Override
    public Iterator<T> iterator() {
        return null;
    }
    
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值