--------------------------------------------------------------------------------------------莫听穿林打叶声,一蓑烟雨任平生--------------------------------------------------------------------------------------------

Java笔记day21

一、先写一个Student类供后面使用

查看代码
public class Student {
    private String name;
    private int age;

    public Student() {
    }

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

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

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

二、集合
1、数组的弊端
    需求:利用数组存储3个学生信息,遍历数组获取每一个学生的信息

查看代码
public class ObjectArrayDemo1 {
    public static void main(String[] args) {
        Student[] arr = new Student[3];

        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        System.out.println("---------------------------------");

        //创建3个学生对象
        Student xiaowang = new Student("王力宏", 40);
        Student dengdeng = new Student("邓超", 45);
        Student huazai = new Student("刘德华", 60);

        //将创建好的3个学生对象,放到数组
        //给对象数组赋值,使用循环是有问题的,因为对象的名字没有规律,没办法
        //将每次循环依次赋值不一样的对象
        //所以给对象数组赋值,只能一个一个赋值
        arr[0] = xiaowang;
        arr[1] = dengdeng;
        arr[2] = huazai;

        //遍历数组获取每一个学生对象
        for (int i = 0; i < arr.length; i++) {
            //System.out.println(arr[i]);
            Student student = arr[i];
            System.out.println(student.getName() + "--" + student.getAge());
        }
    }
}


    赋值即过程解读
    1)、Student[] arr = new Student[3];
        程序执行到这里,方法区里的class文件区有Student.class和ObjectArrayDemo1.class
        在栈里先建立一个main()主方法区,放入Student[] arr
        在堆里新建new Student[3];数组,此时未赋值,输出arr[i]的时候是三个null
        此时假设new Student[3]地址值是0x01,把0x01的值赋值给Student[] arr
    2)、Student xiaowang = new Student("王力宏", 40);...
        在栈里新建Student xiaowang,而在堆里的区域新建new Student
        赋值之前new Student里面是两个null,赋值之后是("王力宏", 40),假设这里的地址值是0x001
        把0x001赋给xiaowang,同样的道理在栈和堆里建立后面的两个对象
    3)、arr[0] = xiaowang;...
        依次给arr[]里的三个null赋上xiaownang...三个对象的地址值
    弊端
        假设在存储完所有的学生对象的后,来了一个新同学A,也要放到该数组中,直接放进去的话,
    由于数组长度已经定下了,只能新建一个数组来存储,新建的数组长度是原来数组长度+1,然后再挨个存放数组
    如果这时候,有一个学生B提前毕业,数组中的元素就少了一个,那么现在数组中就有一个空的位置,
    而这个空的位置依旧是占用内存的,也不太好,所以又要创建一个新的数组,长度-1,然后挨个存放。
        这个例子,无论是从增加还是删除,都非常麻烦,其实原则上我们修改是根据原先的东西基础上进行修改的。
    这时候我们想到之前还学过一个容器,叫做StringBuffer,它就可以根据元素的多少来改变长度。但是,
    StringBuffer里面存储始终是一个一个的字符,而我们现在需要存放学生对象,所以用StringBuffer也不合适。

   
    

2、集合的引入
    1)、集合概述
    在上一个例子当中,就充分体现了数组和String Buffer的弊端,那么有没有一个新的东西让我们来解决这个问题呢
Java替我们考虑到了这一点,根据存储的元素不同,元素的特点不同以及存储方式不同,提供了一个集合继承体系给我们,
简单来说,就是集合
    集合和数组的不同点:
        1、数组的长度是不可变的,集合是可以改变
        2、数组可以存放同一种基本数据类型或者引用数据类型
            而集合只能存放引用数据类型,并且集合中可以存放不同的引用数据类型
            (我们虽然说了集合可以存放不同的引用数据类型,确实也可以这么做,但是,开发中
            一个集合存放一种引用数据类型。)
    集合可以存放各种各样的数据,每种数据的长度,大小以及自身的特点都不一样。
所以,java提供的集合也应该不能够是单一的,我们要针对不同的需求,java提供不同的集合类。
这么多不同的集合,它们的底层数据结构也是不同的,不同并不重要,我们只要知道集合是可以用来
存放东西的,不光可以存放,而且可以去使用这些东西,比如:查找获取,判断等等。
    既然可以上面的操作,这些不同的集合类应该有某种共性的内容,所以我们根据集合的共性内容不断地
向上提取,最终整体形成一个继承体系。
    2)、集合以及集合的功能
    Collection:
        是集合中的顶层接口,它存在由它扩展开来的继承体系,为什么要分出很多不同的集合?
    根据元素是否唯一,是否有序来区分这么多集合(后面的课程中会一一介绍)(List也是接口,ArrayList那一层是类)
    集合学习体系
    图
    Collection:
        1、添加功能
            boolean add(Object obj) 确保此集合包含指定的元素(可选操作)。
            boolean addAll(Collection c)
                将指定集合中的所有元素添加到此集合(可选操作)。
        2、删除功能
            boolean remove(Object o)
                从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
            boolean removeAll(Collection<?> c)
                删除指定集合中包含的所有此集合的元素(可选操作)。
            void clear()
                从此集合中删除所有元素(可选操作)。
        3、获取功能
            Iterator<E> iterator() 返回此集合中的元素的迭代器。
        4、判断功能
            boolean contains(Object o)
                如果此集合包含指定的元素,则返回 true 。
            boolean containsAll(Collection<?> c)
                如果此集合包含指定 集合中的所有元素,则返回true。
            boolean isEmpty()
                如果此集合不包含元素,则返回 true 。
        5、获取长度功能
            int size()
                返回此集合中的元素数。
        6、求交集功能
            boolean retainAll(Collection<?> c)
                仅保留此集合中包含在指定集合中的元素(可选操作)。
        7、将集合转换成数组
            Object[] toArray()
                返回一个包含此集合中所有元素的数组。
 

查看代码
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo1 {
    public static void main(String[] args) {
        //通过子类的形式创建对象,这叫接口多态
        Collection c = new ArrayList();

        //boolean add(Object obj) 确保此集合包含指定的元素(可选操作)。
        System.out.println(c.add("hello"));     //只能判定插入成功或者失败
        System.out.println(c.add("hello"));     //允许有重复的元素
        c.add(20);                              //自动装箱转成了Interger类
        c.add(12.34);

        //void clear()
        //从此集合中删除所有元素(可选操作)。
        //c.clear();

        //boolean remove(Object o)
        //从该集合中删除指定元素的单个实例(如果存在)(可选操作)。
        //只移除一个符合条件的
        System.out.println("从该集合中删除指定元素" + c.remove("hello"));       //clear清除之后不含有Hello,false

        //boolean contains(Object o)
        //如果此集合包含指定的元素,则返回 true 。
        System.out.println(c.contains("hello"));        //上面只删除了一个,true

        //boolean isEmpty()
        //如果此集合不包含元素,则返回 true 。
        System.out.println(c.isEmpty());        //false

        //获取长度功能int size()
        // 返回此集合中的元素数。
        System.out.println(c.size());           //3


        //String toString()
        //返回此集合的字符串表示形式。  AbstractCollection类中的toString()方法
        /**
         * java.lang.Object
         *      java.util.AbstractCollection<E>     //toString是在这里重写的
         *          java.util.AbstractList<E>
         *              java.util.ArrayList<E>
         */
        System.out.println("集合c: " + c);      //重写了toString方法,而且输出的时候还有中括号和逗号
    }
}

3、集合中接口成员方法
    boolean addAll(Collection c)
    boolean removeAll(Collection c)
    boolean containsAll(Collection c)
    boolean retainAll(Collection c)

查看代码
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo2 {
    public static void main(String[] args) {
        //创建一个集合对象
        Collection c1 = new ArrayList();

        //向集合中添加元素
        c1.add("hello");
        c1.add("world");
        c1.add("java");
        c1.add("hadoop");
        c1.add("hive");
        //c1.add("spark");

        //定义另一个集合
        Collection c2 = new ArrayList();
        c2.add("hello");
        c2.add("world");
        c2.add("hive");
        c2.add("spark");
        System.out.println("c1: "+c1);
        System.out.println("c2: "+c2);
        System.out.println("===============================");

        //boolean addAll(Collection c)
        //System.out.println("将c2添加到从c1中:");
        //System.out.println(c1.addAll(c2));    //add是把c2当作一个元素整体添加到c1,addAll是把c2的每一个元素添加到c1中
        //System.out.println("c1: "+c1);
        //System.out.println("c2: "+c2);

        //System.out.println("===============================");
        //boolean removeAll(Collection c) 删除指定集合中包含的所有此集合的元素(可选操作)。
        // 此调用返回后,此集合将不包含与指定集合相同的元素。
        //System.out.println(c1.removeAll(c2));
        //System.out.println("c1: "+c1);
        //System.out.println("c2: "+c2);
        //System.out.println("===============================");
        //boolean containsAll(Collection c)如果此集合包含指定 集合中的所有元素,则返回true。
        //System.out.println(c1.containsAll(c2));
        System.out.println("===============================");
        //boolean retainAll(Collection c)
        //仅保留此集合中包含在指定集合中的元素(可选操作)。
        // 换句话说,从该集合中删除所有不包含在指定集合中的元素。

        //假设有两个集合 c1,c2
        //c1对c2做交集,最终的结果保存在c1中,c2不变
        //并且c1中删除与c2不是共同的其他元素
        //System.out.println(c1.retainAll(c2));
        //System.out.println("c1: "+c1);
        //System.out.println("c2: "+c2);
    }
}

三、迭代器
1、不使用迭代器的遍历
    集合的遍历:目的就是将集合中的元素依次取出来
        Object[] toArray()
        把集合转成数组,可以实现集合的遍历
    例一:

查看代码
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo3 {
    public static void main(String[] args) {
        //创建集合对象
        Collection c1 = new ArrayList();

        //添加元素
        c1.add("hello");
        c1.add("world");
        c1.add("java");
        c1.add("20");
        //c1.add(10);

        //将集合转换成数组
        Object[] array = c1.toArray();

        //遍历数组获取数组中每一个元素
        for (int i = 0; i < array.length; i++) {
        //System.out.println(array[i]);
            //因为获取到的元素类型是Object类型
            //元素是Object,但是数组本身有.length方法
            //所以没有length()方法
            //要想调用字符串中的方法,就需要进行向下转型
        //System.out.println(array[i].length());

            String s = (String) array[i];
            //如果集合中有数字,那么此处转型就不能就会报错,Interger类型不能转型成Strig类型
            //所以集合中得到与元素最好都是同一种类型
            System.out.println(s + ",长度为:" + s.length());
        }
    }
}


    例二:
    需求:向集合中添加3个学生对象,并遍历学生信息

查看代码
import java.util.ArrayList;
import java.util.Collection;
public class CollectionDemo4 {
    public static void main(String[] args) {
        //创建集合
        Collection c1 = new ArrayList();

        //创建3个学生对象
        Student s1 = new Student("李玉伟", 18);
        Student s2 = new Student("刘生发", 17);
        Student s3 = new Student("朱佳乐", 16);

        //将学生对象添加到集合中
        c1.add(s1);
        c1.add(s2);
        c1.add(s3);

        //将学生对象集合转成数组
        Object[] array = c1.toArray();

        //遍历数组
        for (int i = 0; i < array.length; i++) {
            //向下转型,转成元素的类型
            Student s = (Student) array[i];
            System.out.println(s.getName() + "--" + s.getAge());
        }
    }
}


2、使用迭代器遍历
    Iterator iterator()
        迭代器,集合的专用遍历方式
    boolean hasNext()
        如果迭代具有更多元素,则返回 true 。
    Object next()
        返回迭代中的下一个元素。

查看代码
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo5 {
    public static void main(String[] args) {
        //创建集合对象
        Collection c1 = new ArrayList();

        //向集合中添加元素
        c1.add("hello");
        c1.add("world");
        c1.add("java");
        c1.add("hadoop");

        //获取c1的迭代器对象
        Iterator iterator = c1.iterator();
        //System.out.println(iterator);     输出java.util.ArrayList$Itr@4554617c

    //第一种迭代
        Object next() 返回迭代中的下一个元素。
        Object obj = iterator.next();
        System.out.println(obj);
        System.out.println(iterator.next());
        System.out.println(iterator.next());
        System.out.println(iterator.next());
        System.out.println(iterator.next());
        //NoSuchElementException,迭代所有元素之后如果继续迭代会出现该异常
        System.out.println(iterator.next());

    //第二种迭代
        /*我们通过观察发现,最后一个System.out.println(iterator.next());
        是多余的,因为此刻已经将迭代器中的元素遍历完了,不应该写,
        我们实际应该在获取之前判断一下下一个位置上是否有元素,如果有就next()获取
        如果没有就不获取
        boolean hasNext() 如果迭代具有更多元素,则返回 true
        */
        if(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        if(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        if(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        if(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        if(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        if(iterator.hasNext()){
            System.out.println(iterator.next());
        }

        if(iterator.hasNext()){
            System.out.println(iterator.next());
        }

    //第三种迭代
        /*通过加入了判断我们发现,虽然代码不报错,也可以将结果元素正确的打印
        但是由于不知道最后一个元素什么时候遍历,所以需要的迭代器个数也是未知的
        此时,可以用循环改进
        */
        //不知道什么时候结束首先想到while循环
        while (iterator.hasNext()) {
            Object next = iterator.next();
            //向下转型
            String s = (String) next;
            System.out.println(s + ",长度为:" + s.length());
        }

        //for循环迭代,但是不推荐推荐使用while循环
        Iterator iterator = c1.iterator();
        for(;iterator.hasNext();){
            Object next = iterator.next();

            //向下转型
            Student s = (Student) next;
            System.out.println(s.getName() + "--" + s.getAge());
        }
    }
}


3、为什么将Iterator一个接口呢?而不是一个类呢?
    将来你需要根据不同的数据创建不同的集合进行存储,每个集合都有自身独有特点,很有可能每一个
集合遍历的顺序特点不一样,所以取值的方式也很有可能不一样,所以不应该直接实现,而是通过一个接口
将来特有的集合要去使用迭代器时候,就实现一下这个接口,添加自己特有的遍历元素逻辑代码。

四、集合例题
/*
    需求:将5个学生对象添加到集合中并遍历
    Collection集合编写代码,完整代码1.0版本
*/

查看代码
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
public class CollectionDemo7 {
    public static void main(String[] args) {
        //创建学生集合对象
        Collection c1 = new ArrayList();

        //创建学生对象
        Student s1 = new Student("罗翔", 16);
        Student s2 = new Student("周某人", 17);
        Student s3 = new Student("徐磊", 18);
        Student s4 = new Student("张牧野", 20);
        Student s5 = new Student("张三", 21);

        //将学生对象添加到集合中
        c1.add(s1);
        c1.add(s2);
        c1.add(s3);
        c1.add(s4);
        c1.add(s5);

        //获取集合中的迭代器对象
        Iterator iterator = c1.iterator();

        //遍历迭代器元素
        while (iterator.hasNext()) {
            Object next = iterator.next();
            //向下转型
            Student s = (Student) next;
            System.out.println(s.getName() + "---" + s.getAge());
        }
    }
}

五、集合Collection的子接口List
1、有序集合(有序指的是存储和取出的顺序一致,不是指排序),允许重复的元素
    举例

查看代码
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ListDemo1 {
    public static void main(String[] args) {
        //创建List集合对象,使用接口多态的形式创建
        List list = new ArrayList();

        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("bigdata");

        Iterator iterator = list.iterator();

        while (iterator.hasNext()) {
            Object next = iterator.next();
            //向下转型
            String s = (String) next;
            System.out.println(s + ",长度为:" + s.length());
        }
    }
}


2、List相关集合特有的功能
    因为List集合拥有下标索引,所以根据这个下标索引衍生出特有方法
        添加功能:
            void add(int index,Object element)
                将指定的元素插入此列表中的指定位置(可选操作)。
        删除功能:
            Object remove(int index)
                删除该列表中指定位置的元素(可选操作)。
        获取功能:
            Object get(int index)
                返回此列表中指定位置的元素。
        修改功能:
            Object set(int index,Object element)
                用指定的元素(可选操作)替换此列表中指定位置的元素。
        List特有迭代器:
            ListIterator<E> listIterator()
                返回列表中的列表迭代器(按适当的顺序)。
    举例             

查看代码
import org.omg.CORBA.StringHolder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListDemo2 {
    public static void main(String[] args) {
        //创建List集合对象
        List list = new ArrayList();

        //添加元素到集合中
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("hadoop");
        System.out.println(list);
        System.out.println("===============================");

        //void add(int index,Object element)
        //将指定的元素插入此列表中的指定位置(可选操作)
        //如果指数超出范围( index < 0 || index > size() ),会抛出异常
        //索引是多少,就把那个位置上的元素往后推一位,然后添加
        list.add(0, "hive");
        System.out.println(list);
        list.add(5, "spark");
        System.out.println(list);
        //注意该方法的索引取值范围
        //IndexOutOfBoundsException: Index: 7, Size: 6
        //list.add(7, "flink");
        //System.out.println(list);
        System.out.println("********************************");

        //Object remove(int index)
        //删除该列表中指定位置的元素(可选操作)。
        //返回被删除的元素,此处为hive,类型为Object类型
        Object obj = list.remove(0);
        System.out.println(obj);
        System.out.println(list);
        System.out.println("******************************");

        //Object get(int index)
        //返回此列表中指定位置的元素。
        //不改变原集合中的元素
        Object obj2 = list.get(3);
        System.out.println(obj2);
        System.out.println(list);
        System.out.println("******************************");

        //Object set(int index,Object element)
        //用指定的元素(可选操作)替换此列表中指定位置的元素。
        //返回的是指定位置被替换的元素
        Object obj3 = list.set(3, "flink");
        System.out.println(obj3);
        System.out.println(list);

        System.out.println("******************************");
        //获取迭代器对象
        Iterator iterator = list.iterator();
        while (iterator.hasNext()) {
            String s = (String) iterator.next();
            System.out.println(s + ",长度为:" + s.length());
        }
    }
}


3、List集合特有的迭代器和遍历方法
    ListIterator extends Iterator
        由于继承自Iterator接口,所以内部一定也有hasNext()方法和next()方法

    Object previous()
        返回列表中的上一个元素,并向后移动光标位置。
        可以反复调用此方法以向后方遍历列表,或者与调用next()进行混合来回。
        (请注意,对next和previous交替调用将next返回相同的元素。)
        1、该方法是倒着遍历迭代器
        2、该方法的获取元素指针与next()获取元素指针是同一个,调用next()是下一个,调用previous()是上一个

    boolean hasPrevious()返回true如果遍历反向列表,列表迭代器有多个元素,判断上一个元素有没有值
        (换句话说,如果previous()将返回一个元素而不是抛出异常,则返回true )。

    注意:
        要想倒着遍历,必须先正着遍历一遍。在开发中很少使用,面试中经常遇到。

查看代码
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorDemo1 {
    public static void main(String[] args) {
        //创建集合对象
        List list = new ArrayList();

        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        list.add("hadoop");

        ListIterator listIterator = list.listIterator();

//        while (listIterator.hasPrevious()) {                  
//            Object previous = listIterator.previous();        
//            String s = (String) previous;                     
//            System.out.println(s + ",长度为:" + s.length());
//        }
        //迭代器指向第一个元素,第一个元素之前是没有元素的
        //NoSuchElementException
        //迭代器一开始的时候指针在第一个位置之前
        //Object previous = listIterator.previous();
        //String s = (String) previous;
        //System.out.println(s + ",长度为:" + s.length());

        //先将指针移动到最后一个元素的位置后面
        //先正着遍历一遍
        System.out.println("正着遍历:");
        while (listIterator.hasNext()){
            Object next = listIterator.next();
            String s = (String) next;
            System.out.println(s + ",长度为:" + s.length());
        }
        System.out.println("************************************");
        System.out.println("倒着遍历:");
        //然后在倒着遍历
        while (listIterator.hasPrevious()){                     //指针再最后一个元素上,先判断上一个元素是否存在
            Object previous = listIterator.previous();          //当前元素赋值,并且指针返回上一个元素
            String s = (String) previous;                       //转型,输出,输出的时候先正着遍历一遍再倒着遍历一遍
            System.out.println(s + ",长度为:" + s.length());
        }
    }
}
    //也就是说Object previous()只有在倒着遍历的时候才能派上用场

3、Collection中的size()方法和List中的get()方法相结合遍历
    该方法只能用于List集合

查看代码
import java.util.ArrayList;
import java.util.List;
public class ListDemo3 {
    public static void main(String[] args) {
        //创建集合对象
        List list = new ArrayList();

        //创建学生对象
        Student s1 = new Student("沫子", 45);
        Student s2 = new Student("李元浩", 22);
        Student s3 = new Student("智勋", 24);
        Student s4 = new Student("呆妹", 22);
        Student s5 = new Student("简自豪", 21);

        //将学生对象添加到集合中
        list.add(s1);
        list.add(s2);
        list.add(s3);
        list.add(s4);
        list.add(s5);

        //size()方法和get()方法的结合使用,
        for (int i = 0; i < list.size(); i++) {
            Object obj = list.get(i);

            //向下转型
            String s = (String) obj;        //等价于Student student = (Student) list.get(i);
            System.out.println(s + ",长度为:" + s.length());
        }
    }
}

 

posted @ 2021-12-19 20:35  等你回眸一笑  阅读(35)  评论(0)    收藏  举报