JAVA List集合、泛型、增强for循环、方法中的可变参数、嵌套集合

JAVA集合

对象数组
  • 案例:
    需求:我有3个学生,请把这个3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。
  • 代码示例:(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;
        }
    }
    
  • 代码示例:(主函数示例:)
    public class MyTest {
        public static void main(String[] args) {
            //需求:我有3个学生,请把这个3个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。
            //		  学生:Student
            //			成员变量:name,age
            //			构造方法:无参,带参
            //			成员方法:getXxx()/setXxx()
            //			存储学生的数组?自己想想应该是什么样子的?
    
            Student s1 = new Student("苏沅湘", 20);
            Student s2 = new Student("崔季宣", 20);
            Student s3 = new Student("周颖", 18);
            //把要把上面三个学生对象存储起来
            //创建对象数组
            Student[] students={s1,s2,s3};
            //遍历对象数组
            for (int i = 0; i < students.length; i++) {
                Student student = students[i];
                System.out.println(student.getName()+"==="+student.getAge());
            }
            //删掉数组中的第三个元素
            Student[] students1 = Arrays.copyOf(students, 2);
            System.out.println(Arrays.toString(students1));
        }
    }
    ----------------------
    输出:
    苏沅湘===20
    崔季宣===20
    周颖===18
    [org.westos.demo.Student@1b6d3586, org.westos.demo.Student@4554617c]
    
  • 根据以上案例可以得到的结论:
    a. 数组作为容器:可以存储多种多样的类型,但是数组作为容器,增删数组中的元素是很不方便的。
    b. 正因为如此,那Java为了我们更方便的去操作(增删改查)容器中的元素,给我们提供了另外一个容器,叫做集合
JAVA集合概述:
  • 概念:
    Java为了我们更方便的去操作(增删改查)容器中的元素(数组的操作有弊端!),给我们提供了另外一个容器,叫做集合。
    面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类。

  • 数组和集合的区别:
    数组:可以存储基本数据类型,也可以存储引用数据类型。
    集合:只能存储引用数据类型
    数组:一定定义,长度不可变
    集合:长度是可变的。
    数组:只能存储同一种数据类型
    集合:可以存储多种数据类型

  • JAVA中由很多类型的集合,具体可以参考**“Collection集合的继承体系:”**
    在这里插入图片描述

Collection集合的功能概述:
  • Collection 接口 是个单列集合的父类:
    示例:
    public class MyTest {
        public static void main(String[] args) {
            // Collection 接口 是个单列集合的父类
            //多态(重点),从继承图中可知:ArrayList是Collection的子类!
            Collection collection = new ArrayList();
            //往集合中添加元素,返回值的意思是 是否添加成功
            boolean b = collection.add("aaa");
            collection.add("bbb");
            collection.add("ccc");
    
            System.out.println(collection);
        }
    }
    --------------
    输出:
    [aaa, bbb, ccc]
    
  • 具体的集合功能可以通过查看API说明手册看到,以下只一部分常用的举例:
  • 功能示例:
    a. 添加功能
    boolean add(Object obj):		添加一个元素(返回的是是否成功)
    boolean addAll(Collection c):	添加一个集合的元素  (给一个集合添加进另一个集合中的所有元素)
    ---------------------
    示例:
    Collection collection1 = new ArrayList();
    collection1.add(100); //自动装箱
    collection1.add(Integer.valueOf(20));
    collection1.add(300);
    collection1.add(400);
    //删掉集合中的元素
    boolean b = collection1.remove(400);
    System.out.println(collection1);
    //清空集合中集合中的元素
    collection1.clear();
    System.out.println(collection1);
    输出:
    [aaa, bbb, ccc, 100, 20, 300, 400]
    [100, 20, 300, 400]
    
    b. 删除功能
    void clear():移除所有元素
    boolean remove(Object o):移除一个元素
    boolean removeAll(Collection c):移除一个集合的元素(移除一个以上返回的就是true) 删除的元素是两个集合的交集元素,如果没有交集元素 则删除失败 返回false
    ------------------------
    示例1:
    Collection collection1 = new ArrayList();
    collection1.add(100); //自动装箱(因为集合中存储的是引用类型!,所以自动装箱成Integer类型的数据!)
    collection1.add(Integer.valueOf(20));//手动装箱
    collection1.add(300);
    collection1.add(400);
    //删掉集合中的元素
    boolean b = collection1.remove(400);
    System.out.println(collection1);
    //清空集合中集合中的元素
    collection1.clear();
    System.out.println(collection1);
    输出:
    [100, 20, 300]
    []
    -------------------
    示例2:
    Collection collection1 = new ArrayList();
    collection1.add(1000); //自动装箱
    collection1.add(2000);
    collection1.add(500);
    Collection collection2 = new ArrayList();
    collection2.add(100); //自动装箱
    collection2.add(400);
    //A集合removeAll(B集合) A 集合会移除掉两个集合的交集元素,如果移除了返回true,没有交集元素返回false
    boolean b = collection1.removeAll(collection2);
    System.out.println(b);
    System.out.println(collection1);
    System.out.println(collection2);
    输出:
    false
    [1000, 2000, 500]
    [100, 400]
    
    c. 判断功能
    boolean contains(Object o):判断集合中是否包含指定的元素	
    boolean containsAll(Collection c):判断集合中是否包含指定的集合元素(这个集合包含另一个集合中所有的元素才算包含 才返回true),比如:123 containsAll 12=true   1,2,3 containsAll 2,3,4=falseboolean isEmpty():判断集合是否为空
    --------------------------
    示例1//与判断相关的方法
    Collection collection1 = new ArrayList();
    collection1.add(1000); //自动装箱
    collection1.add(4000);
    collection1.add(500);
    //判断集合中是否有这个元素
    boolean b = collection1.contains(500);
    System.out.println(b);
    输出:
    true
    ------------------------
    示例2:
    Collection collection1 = new ArrayList();
    collection1.add(1000); //自动装箱
    collection1.add(500);
    //获取集合的长度
    int size = collection1.size();
    System.out.println(size);
    collection1.clear();
    //判断一个集合是否为空
    boolean empty = collection1.isEmpty();
    System.out.println(empty);
    //"".isEmpty(); 字符串也有一个判断是否为空的方法!
    
    d. 获取功能:集合只能通过迭代器进行迭代!
    Iterator<E> iterator()(重点)
    -----------------------
    示例:
    Collection collection1 = new ArrayList();
    collection1.add(1000); //自动装箱
    collection1.add(2000);
    collection1.add(3000);
    collection1.add(4000);
    collection1.add(4000);
    collection1.add(500);
    
    //遍历Collection集合需要获取一个迭代器
    //对 collection 进行迭代的迭代器
    /* boolean hasNext ()
    如果仍有元素可以迭代,则返回 true。
    E next ()
    返回迭代的下一个元素。*/
    
    // 接口 Iterator<E >
    Iterator iterator = collection1.iterator();
    //java.util.ArrayList$Itr @ 1 b6d3586
    Object next = iterator.next();//手动移动
    System.out.println(next);
    System.out.println(iterator);
    while (iterator.hasNext()){
        Object obj= iterator.next();
        System.out.println(obj);
    }
    System.out.println(collection1);
    输出:
    1000
    java.util.ArrayList$Itr@1b6d3586(这个iterator是一个内部类的对象!(通过打印地址值发现!,但通过追踪源码我无法得出此结论!))
    								  定义为内部类的好处:可以直接访问集合中的对象!(内部类可以访问外部类的信息!)
    2000
    3000
    4000
    4000
    500
    [1000, 2000, 3000, 4000, 4000, 500] (说明迭代器进行迭代的时候,只是迭代指针发生了变化,而集合本身并没有发生滨化!)
    ----------------------------------
    示例2(Student类的定义在本文第一部分已经给出了)
    Student s1 = new Student("苏沅湘", 20);
    Student s2 = new Student("崔季宣", 20);
    Student s3 = new Student("周颖", 18);
    Collection collection = new ArrayList();
    collection.add(s1);
    collection.add(s2);
    collection.add(s3);
    Iterator iterator = collection.iterator();
    while (iterator.hasNext()){
        Object next = iterator.next();
        //向下转型
        Student student= (Student) next;
        System.out.println(student.getName()+"==="+student.getAge());
        }
    -------------------------
    输出:
    苏沅湘===20
    崔季宣===20
    周颖===18
    
    e. 长度功能
    int size():元素的个数
    面试题:数组有没有length()方法呢?字符串有没有length()方法呢?集合有没有length()方法呢?
    回答:数组有,字符串有,集合没有(集合是size)
    f. 交集功能
    例如:A集合对B集合取交集,获取到的交集元素在A集合中。返回的布尔值表示的是A集合是否发生变化 
    boolean retainAll(Collection c):获取两个集合的交集元素(交集:两个集合都有的元素)
    ----------
    示例:
    //取两个集合的交集元素
        Collection collection1 = new ArrayList();
        collection1.add(100); //自动装箱
        collection1.add(200);
        collection1.add(300);
        collection1.add(400);
        collection1.add(4000);
        collection1.add(500);
    
        Collection collection2 = new ArrayList();
        collection2.add(100); //自动装箱
        collection2.add(200);
        collection2.add(300);
        collection2.add(400);
        collection2.add(600);
    	//例如:A集合对B集合取交集,获取到的交集元素在A集合中。返回的布尔值表示的是A集合是否发生变化 发生过变化返回true 没有发生变化返回false
        boolean b = collection1.retainAll(collection2);
        System.out.println(b);
        System.out.println(collection1);
        System.out.println(collection2);
        输出:
        true
    	[100, 200, 300, 400](collection1中只剩下了交集的元素)
    	[100, 200, 300, 400, 600](collection2的元素未发生变化)
    
    g. 把集合转换为数组
    Object[] toArray()
    ---------------
    示例:
    Collection collection1 = new ArrayList();
    collection1.add(1000); //自动装箱
    collection1.add(2000);
    collection1.add(3000);
    collection1.add(4000);
    collection1.add(4000);
    collection1.add(500);
    把一个集合转换成数组(手动版:)
    Integer[] integers = new Integer[collection1.size()];
    Iterator iterator = collection1.iterator();
    int i=0;
    while (iterator.hasNext()){
        Object next = iterator.next();
        Integer integer= (Integer) next;
        integers[i++]=integer;
    }
    System.out.println(Arrays.toString(integers));
    toArray();把一个集合转换成数组(这个数组是Object型的)
    Object[] objects = collection1.toArray();
    //遍历途中可以对元素进行向下转型(必须向下转型才能获取相应的数值!)
    for (int j = 0; j < objects.length; j++) {
        Integer object = (Integer) objects[j];
        System.out.println(object.intValue());
    }
    输出:
    [1000, 2000, 3000, 4000, 4000, 500]
    1000
    2000
    3000
    4000
    4000
    500
    
  • IDEA小技巧:按住alt操作鼠标,多列选中,对多列同时进行操作!
JAVA集合——list类
List概述及特点
  • List概述及特点: 元素有序,并且每一个元素都存在一个索引.元素可以重复.(这里的有序指的是:可以通过索引来获取元素!)
  • List集合的特有功能概述:
    void add(int index,E element):		在指定索引处添加元素
    E remove(int index):				移除指定索引处的元素  返回的是移除的元素
    E get(int index):					获取指定索引处的元素
    E set(int index,E element):			更改指定索引处的元素 返回的而是被替换的元素
    
  • 根据元素查找索引:
    int index = list.indexOf(100);
    int index2 = list.lastIndexOf(100);
    
  • 遍历集合中的元素:(相当于创建了一个匿名内部类)
    list.forEach(new Consumer()){
        @Override
        public void accept(Object o){
            System.out.println(o);
        }
    }
    
  • 上面遍历的方法可以用Lambda进行简化表示:(简化上面匿名内部类的写法!)
    //可以使用Lambda 简化上面的写法
    System.out.println("===========================");
    list.forEach((obj)->System.out.println(obj));
    
List的遍历:(案例)
  • 案例:List集合遍历(应该有三种方法:两种迭代器,一种for循环)
    public class MyTest3 {
        public static void main(String[] args) {
            List list = new ArrayList();
    
            list.add(1000); //自动装箱
            list.add(2000);
            list.add(3000);
            list.add(4000);
            list.add(4000);
            list.add(500);
            
            //遍历方式1: 利用Colletction的迭代器
            //list.iterator()
            //遍历方式2:List 有一个自己的迭代器
            ListIterator listIterator = list.listIterator();
            while (listIterator.hasNext()){
                Object next = listIterator.next();
                System.out.println(next);
            }
            System.out.println("==============================");
            //遍历方式3 采用for循环遍历
            for (int i = 0; i < list.size(); i++) {
                Object o = list.get(i);
                System.out.println(o);
            }
        }
    }
    ---------
    输出:
    
    1000
    2000
    3000
    4000
    4000
    500
    ==============================
    1000
    2000
    3000
    4000
    4000
    500
    
  • 案例:List集合存储学生对象并遍历
    public class MyTest4 {
        public static void main(String[] args) {
            Student s1 = new Student("苏沅湘", 20);
            Student s2 = new Student("崔季宣", 20);
            Student s3 = new Student("周颖", 18);
            List arrayList = new ArrayList();
            arrayList.add(s1);
            arrayList.add(s2);
            arrayList.add(s3);
            for (int i = 0; i < arrayList.size(); i++) {
                Object o = arrayList.get(i);
                Student student= (Student) o;
                System.out.println(student.getName()+"==="+ student.getAge());
            }
        }
    }
    -------------
    输出:
    苏沅湘===20
    崔季宣===20
    周颖===18
    
ListIterator的特有功能:
  • 概念:ListIterator 继承自Iterator 可以使用Iterator中的方法
  • ListIterator的特有功能:
    	boolean hasPrevious():			是否存在前一个元素
    ​	E previous():					返回列表中的前一个元素
    
    注意:
    a. 以上两个方法组合可以实现反向遍历,但是注意:要完成反向遍历之前要先进行正向遍历 ,这样指针才能移到最后
    ​ b. 如果直接反向遍历是没有效果的 ,因为指针默认位置就在最前面 他前面没有元素。
List的三个子类的特点:
  • List的三个子类的特点:
    • ArrayList:
      底层数据结构是数组,查询快,增删慢。
      线程不安全,效率高。
    • Vector:
      底层数据结构是数组,查询快,增删慢。
      线程安全,效率低。
    • LinkedList:
      底层数据结构是链表,查询慢,增删快。
      线程不安全,效率高。
  • List有三个子集合,我们到底使用谁呢?
    要安全还是要效率?
    是查找多还是增删多?
    (根据以上特性来选择!)
并发修改异常产生的原因及解决方案
  • 案例演示:(需求:我有一个集合,我想判断里面有没有 “world” 这个元素,如果有,我就添加一个 “javaee” 元素,请写代码实现。)
    public class MyTest2 {
        public static void main(String[] args) {
          /*  需求:我有一个集合,请问,我想判断里面有没有 "world" 这个元素,
          如果有,我就添加一个 "javaee" 元素,请写代码实现。*/
            List list = new ArrayList();
            list.add("aaa");
            list.add("bbb");
            list.add("ccc");
            list.add("world");
    
    		方式1/* if (list.contains("world")) {
                list.add("javaee");
            }
            System.out.println(list);
    */
    		方式2// ConcurrentModificationException 并发修改异常
            //当你使用迭代器,对集合的元素,进行迭代,那么在迭代途中,先要增删集合中的元素,就会出现并发修改异常
            //为什么?是因为,通过集合获取到,这个迭代器之后,迭代器,已经预先知道,集合中的元素个数,会按照既定的元素个数进行迭代,那么在迭代途中,你突然要增删元素,就会打乱迭代器的迭代顺序,所以就会抛出并发修改异常
            ListIterator listIterator = list.listIterator();
            while (listIterator.hasNext()) {
                Object next = listIterator.next();
                String ele = (String) next;
                if (ele.equals("world")) {
                    //list.add("javaee");  	// 这样的写法会报错
                    //  list.remove("aaa");	// 这样的写法会报错
                    listIterator.add("javaee");
                }
            }
           	System.out.println(list);
           	//方式3 使用for循环遍历
    
            for (int i = 0; i < list.size(); i++) {
                if (list.get(i).equals("aaa")) {
                    list.add("vvvv");
                }
            }
            System.out.println(list);
        }
    }
    
  • ConcurrentModificationException 并发修改异常:
    当你使用迭代器,对集合元素,进行迭代,那么在迭代途中,如果要增删集合中的元素,就会出现冰法修改异常
  • 原因:
    因为,通过集合获取到这个迭代器之后,迭代器,已经预先知道,集合总的元素个数,会按照既定的元素个数进行迭代,那么在迭代途中,你突然要增删元素,就会打乱迭代其的迭代顺序,所以就会抛出并发修改异常。
  • 解决方式:
    解决方式1:(如果使用迭代器遍历,那么在遍历途中,想要增删元素,那么你就使用迭代器自带的增删元素的方法)
    解决方式2:使用for循环遍历
数据结构的理解与特性
  • 数据结构概述及常见数据结构:
    数据结构其实就是存储数据的格式
    分类: 栈 , 队列 , 数组 , 链表 , 树 , 哈希表
  • 栈特点: 先进后出
  • 队列: 先进先出
  • 数组特点: 查询快 , 增删慢
  • 链表特点: 查询慢 , 增删快
JAVA集合——ArrayList
ArrayList存储与遍历
  • JDK1.8新增的一个方法也能遍历集合
    ​ void forEach(Consumer<? super E> action) 执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常
  • 其他遍历操作:
    迭代器(因为ArrayList还是List的子类,可以利用Collection的迭代器或者List独有的迭代器)
    普通for(因为ArrayList还是List的子类)
    
  • 示例:
    public class MyTest {
        public static void main(String[] args) {
            //
            ArrayList list = new ArrayList(); ArrayList指向(这次与以往不同,不是由Collection或者List指向它,利用多态进行访问了!)
          	/*  int lastIndexOf (Object o)
            返回此列表中最后一次出现的指定元素的索引,或如果此列表不包含索引,则返回 - 1。
            int indexOf (Object o)
            返回此列表中首次出现的指定元素的索引,或如果此列表不包含元素,则返回 - 1。
            void forEach (Consumer < ? super E > action)
            执行特定动作的每一个元素的 Iterable直到所有元素都被处理或操作抛出异常。*/
    
            list.add(100);
            list.add(200);
            list.add(300);
            list.add(100);
            list.add(400);
            list.add(500);
            //根据元素查找改元素第一次出现的索引
            int index = list.indexOf(100);
            System.out.println(index);
            int i = list.lastIndexOf(100);
            System.out.println(i);
    
            for (int i1 = 0; i1 < list.size(); i1++) {
                System.out.println(list.get(i1));
            }
            System.out.println("===========================");
            //Consumer
            //遍历集合中的元素
            list.forEach(new Consumer() {
                @Override
                public void accept(Object o) {
                    System.out.println(o);
                }
            });
            //可以使用Lambda 简化上面的写法
            System.out.println("===========================");
            list.forEach((obj)->System.out.println(obj));
        }
    }
    
案例:(去除ArrayList中的重复数值)
  • 示例1:(不采取额外的存储结构)
    public class MyTest2 {
        public static void main(String[] args) {
            ArrayList list = new ArrayList();
            list.add(100);
            list.add(100);
            list.add(100);
            list.add(100);
            list.add(100);
            list.add(100);
            list.add(200);
            list.add(100);
            list.add(200);
            list.add(100);
            list.add(200);
            list.add(100);
            list.add(200);
            list.add(300);
            list.add(100);
            list.add(400);
            list.add(500);
            list.add(100);
            list.add(200);
            list.add(300);
            list.add(100);
            list.add(400);
            list.add(500);
            list.add(100);
            list.add(200);
            list.add(100);
            list.add(200);
            //去除集合中的重复元素
            //每次拿一个元素,跟后面的每个元素取比较,如果遇到相同的,就删除
            for (int i = 0; i < list.size(); i++) {
                for (int j = i + 1; j < list.size(); j++) {
                   /* Object o = list.get(i);
                    Object o1 = list.get(j)*/;
                    if(list.get(i).equals(list.get(j))){
                        list.remove(j);
                        j--;//记得 j--(重点!)
                    }
                }
            }
            System.out.println(list);
    
          //  HashSet hashSet = new HashSet<>(list);
          //  System.out.println(hashSet);
        }
    }
    
  • 示例2:去除集合中字符串的重复值(可以采用辅助的数据结构)
    public class MyTest {
        public static void main(String[] args) {
            /*A:
            案例演示
            需求:ArrayList去除集合中字符串的重复值(字符串的内容相同)
            思路:创建新集合方式*/
            ArrayList list = new ArrayList();
            list.add("abc");
            list.add("abc");
            list.add("abc");
            list.add("abc");
            list.add("bbb");
            list.add("abc");
            list.add("ccc");
            list.add("aaa");
    
            ArrayList newList = new ArrayList();
            for (int i = 0; i < list.size(); i++) {
                Object o = list.get(i);
                if(!newList.contains(o)){
                    newList.add(o);
                }
            }
            System.out.println(newList);
        }
    }
    -------------
    输出:
    [abc, bbb, ccc, aaa]
    
  • 示例3:(去除自定义类对象的重复值,即:对象的成员变量值相同)
    自定义学生类:
    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 boolean equals(Object o) {   //必要的重写部分:
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;
            Student student = (Student) o;
            return age == student.age &&
                    Objects.equals(name, student.name);
        }
    
    
        @Override
        public int hashCode() {   //非必要重写这部分!
            return Objects.hash(name, age);
        }
    }
    
    主函数:
    public class MyTest2 {
        public static void main(String[] args) {
            Student s1 = new Student("张三", 23);
            Student s2 = new Student("张三", 23);
            Student s3 = new Student("张三", 23);
            Student s4 = new Student("张三2", 23);
            Student s5 = new Student("张三3", 23);
            ArrayList list = new ArrayList();
            list.add(s1);
            list.add(s2);
            list.add(s3);
            list.add(s4);
            list.add(s5);
            ArrayList newList = new ArrayList();
            for (int i = 0; i < list.size(); i++) {
                Object o = list.get(i);
                if(!newList.contains(o)){   重点在这里,为何它可以对比出不同对象是否是我们要删除的标准?
                    newList.add(o);
                }
            }
    
            System.out.println("=============");
            for (int i = 0; i < newList.size(); i++) {
               Student stu = (Student) newList.get(i);
                System.out.println(stu.getName()+"==="+stu.getAge());
            }
            
        }
    }
    -------------------
    输出:
    =============(这里刚好得到我们想要的结果!)
    张三===23
    张三2===23
    张三3===23
    
    引出问题:contains()为何能知道我们比对的标准是什么?
    追踪contains()源码可知:
    在ArrayList.java文件下,得到:
    public boolean contains(Object o) {
            return indexOf(o) >= 0;
        }
    -------------------
    进一步追踪,这里的indexOf()就是ArrayList.java下的indexOF()
    public int indexOf(Object o) {
            if (o == null) {
                for (int i = 0; i < size; i++)
                    if (elementData[i]==null)
                        return i;
            } else {
                for (int i = 0; i < size; i++)
                    if (o.equals(elementData[i]))   发现了重点:它会调用对象的equals()方法进行对比!(恰好我们在自定义的Student类中重写了equals()方法!,所以达到了我们想要的对比效果!)
                        return i;
            }
            return -1;
        }
    
Java集合——Vector
Vector的概述:
  • 概述:Vector 类可以实现可增长的对象数组 , Vector 是同步的。
  • 特点:Vector 底层数据结构是数组,查询快,增删慢,线程安全效率低
Vector类特有功能:
  • 功能:
    public void addElement(E obj) 添加元素的另一种方法
    public E elementAt(int index) 获取元素的另一种方法
    public Enumeration elements() 返回可迭代的迭代器
    
  • 案例演示:
    public class MyTest {
        public static void main(String[] args) {
           //Vector 底层数据结构是数组,查询快,增删慢,线程安全效率低
    
          /*  public void addElement (E obj)
            public E elementAt ( int index)
            public Enumeration elements ()*/
            Vector vector = new Vector();
            vector.add(200);
            vector.addElement(
            300);
            vector.add(200);
            vector.addElement(300);
            vector.add(200);
            vector.addElement(300);
            Object ox = vector.get(0);
            Object o1 = vector.elementAt(0);
            System.out.println(o1 == ox); 返回true,则说明这两种取元素的方法效果是一致的!
             /* 
            lastElement()返回向量的最后一个组件。
            firstElement()返回第一个组件(在指数 0项目)这个载体。
            removeElement(Object obj)从该向量中移除第一个(最低索引)发生的参数。
            void removeElementAt(int index)在指定的索引中删除组件。
            setElementAt(E obj, int index)设置组件在指定的index这个向量是指定的对象。
    
            */
             //遍历方法:
            Enumeration elements = vector.elements();
            while (elements.hasMoreElements()){
                Object o = elements.nextElement();
                System.out.println(o);
            }
            
        }
    }
    ----------------
    输出:
    true
    200
    300
    200
    300
    200
    300
    
JAVA集合——LinkedList
LinkedList概述:
  • 概述:List 接口的链接列表实现 , 此实现不是同步的
  • 特点:LinkedList 底层数据结构是链表,增删快查询慢,线程不安全效率高
LinkedList特有的功能:
  • 功能:

    public void addFirst(E e)addLast(E e)
    public E getFirst()getLast()
    public E removeFirst()public E removeLast()
    
  • 特有功能示例:

    public class MyTest {
        public static void main(String[] args) {
            //LinkedList 底层数据结构是链表,增删快查询慢,线程不安全效率高
            /*
              void addFirst(E e)在此列表的开始处插入指定的元素。
              void addLast(E e)将指定的元素列表的结束。
              public void addFirst(E e)及addLast(E e)
    	      public E getFirst()及getLast()
    	      public E removeFirst()及public E removeLast()
            */
            LinkedList linkedList = new LinkedList();
            linkedList.addLast("eeee");
            linkedList.add("aaa");
            linkedList.addFirst("bbb");
            linkedList.add("ccc");
            System.out.println(linkedList);
    
            Object o = linkedList.get(0);
            System.out.println(o);
            Object first = linkedList.getFirst();
            System.out.println(first);
            Object first2 = linkedList.getFirst();
            System.out.println(first2);
            
            System.out.println(linkedList);
        }
    }
    -------------
    输出:
    [bbb, eeee, aaa, ccc]
    bbb
    bbb
    bbb
    [bbb, eeee, aaa, ccc]
    
LinkedList案例:(模拟栈的数据结构)
  • 示例:(自定义List类)
    public class MyList {
        LinkedList linkedList;
        public MyList() {
            linkedList= new LinkedList();
        }
    
        public void addObj(Object obj) {
           linkedList.addFirst(obj);
        }
    
        public Object get() {
            Object obj= linkedList.pop();
            linkedList.addLast(obj);  //这样做的目的是:操作完后,原来的数据还在!(但个人感觉好像挺没必要的!)
            return obj;
        }
    }
    
  • 示例2:(主函数)
    public class MyTest {
        public static void main(String[] args) {
            //需求:请用LinkedList模拟栈数据结构的集合,并测试
    
            MyList myList = new MyList();
            myList.addObj(100);
            myList.addObj(200);
            myList.addObj(300);
            myList.addObj(400);
            myList.addObj(500);
    
            Object obj=myList.get();
            System.out.println(obj);
            obj = myList.get();
            System.out.println(obj);
            obj = myList.get();
            System.out.println(obj);
            obj = myList.get();
            System.out.println(obj);
            obj = myList.get();
            System.out.println(obj);
            System.out.println("==============");
            obj = myList.get();
            System.out.println(obj);
        }
    }
    -----------------
    输出:
    500
    400
    300
    200
    100
    ==============
    500(这里可以看到,当遍历完一回以后,数据元素没有发生变化!)
    
JAVA泛型:
概述和基本使用:
  • 泛型的由来:
    ObjectTool
    泛型的由来:通过Object转型问题引入
    早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。
    也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
  • 概念:
    如果我们使用了泛型,就可以明确集合中到底放了什么样的数据类型。
    泛型机制:是JDK1.5引入的,是一种将数据类型明确的工作,推迟到创建对象,或调用方法时,再去明确的一种机制。
    也就是:参数化类型,把类型当作参数一样的传递。
  • 定义方法:
    泛型可以使用在类、接口 方法 <引用类型,引用类型>
    ------------------
    例如:(在创建ArrayList对象的时候传入指定的泛型为:String,则ArrayList中只能存储这一种类型,若不传入:则默认为:Object类型,所以获取的时候,需要显示地进行向下转换!)
    ArrayList<String> list1 = new ArrayList<Sring>()
    
  • 泛型的好处:
    (1): 把运行时期的问题提前到了编译期间(这句话的含义不太懂?难道是指的避免了运行时候向下转换所造成的报错?这个编译器和运行期到底怎么解释的?编译器不行但是运行期可以(反射)?)
    (2): 避免了强制类型转换
    (3):优化了程序设计,解决了黄色警告线
  • 集合明确了泛型的具体类型,那么这个集合就只能存储这种类型(避免向下转型)
    示例:
    示例:(避免向下转型)
    查看上课所述!
    //集合可以存储多种引用数据类型。
    ArrayList list = new ArrayList();(这里没有专门指定泛型的类型声明,则默认为:Object)
    list.add("abc");
    list.add(200);
    list.add(new StringBuffer());
    Object o = list.get(0);
    String str= (String) o;(向下转型)
    int length = str.length();
    -------------------------
    //集合明确了泛型的具体类型,那么这个集合只能存储这种类型
    ArrayList<String> list1 = new ArrayList<String>();
    list1.add("abc");
    list1.add("abc");
    list1.add("abc");
    String s = list1.get(0); //这里直接获取就OK,不需要向下转型
    
泛型的好处的演示:(自定义类中使用泛型!)
  • 一般通用类型的定义方法:(拥有扩展性,但是必须使用向下转型才能使用!)
    public class MyClass {
        private Object obj;
    
        public Object getObj() {
            return obj;
        }
    
        public void setObj(Object obj) {
            this.obj = obj;
        }
    }
    ----------------------------------------
    public class MyTest {
        public static void main(String[] args) {
    
            //定义类时,或方法时,都想考虑这个扩展性
            MyClass myClass = new MyClass();
            myClass.setObj(100);
            Object obj = myClass.getObj();
            Integer integer= (Integer) obj; // 向下转型
    
            MyClass myClass1 = new MyClass();
            myClass1.setObj("abc");
            Object obj1 = myClass1.getObj();
            String string= (String) obj1;
        }
    }
    
  • 泛型定义方法:(既拥有了扩展性,同时也避免了向下转型!)
    public class MyDem<T> { //T 泛型(在类中定义!)
        private T obj;
    
        public T getObj() {
            return obj;
        }
    
        public void setObj(T obj) {
            this.obj = obj;
        }
    }
    -----------------------------
    public class MyTest {
        public static void main(String[] args) {
            //设计一个类,既要扩展性,也不想向下转型。
            //设计一个泛型类,给类加上泛型
            //class A<T>{}
            //泛型机制:是JDK1.5引入的,是一种将数据类型明确工作,推迟到创建对象,或调用方法时,再去明确的一种机制。
            MyDem<String> myDem = new MyDem<>(); 由于前面已经声明了泛型的指代为:String,后面的<>中的泛型指定可以省略。
            myDem.setObj("abc");
            String obj = myDem.getObj();
            System.out.println(obj);
    		//如不注明,则说明:泛型为Object!
            MyDem<Integer> integerMyDem = new MyDem<>();
            integerMyDem.setObj(200);
            Integer obj1 = integerMyDem.getObj();
            new ArrayList<Integer>(); //指明了ArrayList中泛型为:Integer,则ArrayList中只能存储Integer类型的数据。
        }
    }
    
多泛型的使用:
  • 示例:(定义泛型的类)
    public class MyHaHa<R,P>{ //多泛型
        private R r;
        private P p;
    
    }
    
  • 示例:(主函数)
    public class MyTest {
        public static void main(String[] args) {
            MyHaHa<Integer, String> integerStringMyHaHa = new MyHaHa<>(); //多泛型的使用!
           // integerStringMyHaHa.set("string");
    
            ArrayList<Integer> integers = new ArrayList<>();
            integers.add(100);
            integers.add(100);
            integers.add(100);
            integers.add(100);
            integers.add(100);
            integers.add(100);
            integers.forEach(new Consumer<Integer>() {
                @Override
                public void accept(Integer integer) {
                    System.out.println(integer);
                }
            });
        }
    }
    ----
    输出:
    100
    100
    100
    100
    100
    100
    
泛型接口的概述和使用
  • 接口上的泛型都是在定义实现其子类的过程中传入的!
  • 示例:(主函数中利用匿名内部类来实现接口的子类)
    public class MyTest {
        public static void main(String[] args) {
            //泛型接口 什么时候去明确
            //匿名内部类
            new MyInterface<Integer,Integer>(){
    
                @Override
                public Integer set(Integer integer) {
                    return null;
                }
            };
        }
    }
    
  • 示例:(接口)
    interface MyInterface<T,R>{   //在接口上使用泛型
        R set(T t);
    }
    
  • 示例:(实现接口的子类)
    //子类在实现接口时,可以以明确接口上的泛型到底是什么类型
    class Son implements MyInterface<String,Integer>{
        @Override
        public Integer set(String s) {
            return null;
        }
    }
    
泛型在方法上的使用:
  • 示例:(自定义类)
class AA{
	原来的办法:(为了考虑通用性)
   /* public void set(Object str) {
        System.out.println(str);
    }*/

   	泛型方法
    public<P> void set(P str) {

        System.out.println(str);
    }
}
  • 主函数:
    public class MyTest {
        public static void main(String[] args) {
            //方法上的泛型,在你调用方法时,再去明确
            AA aa = new AA();
            aa.set(3.14); //这里没有专门指定泛型的语法,确也可以(神奇!!!!)
            aa.set(200);
            aa.set("abc");
        }
    }
    
  • 泛型一般在类和接口上使用的比较多!
泛型高级之通配符:
  • 泛型通配符<?>:
    任意类型,如果没有明确,那么就是Object以及任意的Java类了

  • 泛型如果明确了数据类型以后,那么要求左右两边的数据类型必须一致

    Collection<Object> col1 = new ArrayList<Object>() ;
    Collection<Object> col2 = new ArrayList<Animal>() ; 报错(前后不一致)
    
  • 泛型统配符号:(前面用统配符号,后面则必须注明!)

    ArrayList<?> objects2 = new ArrayList<cat>(); 这种方法就不需要前后都一致了!
    
  • ? extends E:向下限定,E及其子类

    Collection<? extends Animal> col9 = new ArrayList<Object>() ; 报错(因为Object不是Animal的子类)
    Collection<? extends Animal> col10 = new ArrayList<Animal>() ; 自己本身也可以
    Collection<? extends Animal> col11 = new ArrayList<Dog>() ;
    
  • ? super E:向上限定,E及其父类

    Collection<? super Animal> col13 = new ArrayList<Object>() ;
    Collection<? super Animal> col14 = new ArrayList<Animal>() ;
    Collection<? super Animal> col15 = new ArrayList<Dog>() ; 报错(因为Dog是Animal的子类而不是父类!)
    
  • 特别注意泛型通配符的一些注意要点,这里面说明了这些泛型通配符在什么场景下使用,该如何使用,有哪些需要注意的坑!(非常重要!)

增强for循环:
  • 概述:主要用来简化数组和Collection集合的遍历(在JDK1.5及以后版本适用)
  • 格式:
    for(元素数据类型 变量 : 数组或者Collection集合) {
    		使用变量即可,该变量就是元素
    	}
    
  • 示例:(遍历数组)
    int[] arr={20,20,30,80};
    --------------------(普通for循环)
    for (int i = 0; i < arr.length; i++) {
         System.out.println(arr[i]);
    }
    --------------------(增强for循环)
    for(int i:arr){
    	System.out.println(arr[i]);
    }
    
  • 示例:(遍历集合)
    ArrayList<Integer> list = new ArrayList<>();
    list.add(200);
    list.add(200);
    list.add(200);
    list.add(200);
    for(Integer num:list){
        System.out.println(num);
    }
    
  • 优点:简化了遍历的写法!
  • 特点:它的底层是用迭代器在进行迭代,所以在迭代过程中不能进行增删元素!),这一点和Python极其像!
    否则,就会报错:java.util.ConcurrentModificationException (并发修改异常!)
  • 普通for循环和增强for循环的适用特点:
    a. 如果循环过程中需要拿索引做判断,那你就使用普通for循环
    b. 如果只是遍历元素看一下,那就使用新式for循环
JAVA可变参数:
  • 可变参数概述:
    定义方法的时候不知道该定义多少个参数(如果也不知道具体类型的话,则可以使用泛型来进行指定!),可变参数(数组)中的数据类型都是一样的(是同属一个类型的数组!)

  • 格式:

    修饰符 返回值类型 方法名(数据类型…  变量名){}
    
  • 注意:
    a. 这里的变量其实是一个数组
    b. 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个

  • 示例:

    public class MyTest {
        public static void main(String[] args) {
            int sum = add(1, 2);
            int sum2 = add(1, 2, 3);
            int sum3 = add(1, 2, 3, 4);
            //可变参数:一次可以接收多个参数
            System.out.println(sum);
            System.out.println(sum2);
            System.out.println(sum3);
    
        }
    
        //可变参数 数据类型 ... 参数名
        //可变参数 本质是个数组
        //如果说一个方法上,有普通参数,也有可变参数,可变参数肯定是最后一个参数
        private static int add(int b,int... num) {
            //System.out.println(num.length);
            int sum=0;
            for (int i : num) { // 增强for循环!
                sum+=i;
            }
            return sum+b;
        }
    }
    
Arrays工具类的asList()方法的使用:
  • 概念:Arrays工具类的asList(T… t)方法的使用,将数组转换成集合。
  • 格式:
    static <T> List < T > asList(T...a)
    
  • 示例:
    public class MyTest {
        public static void main(String[] args) {
            Integer[] integers = {20, 30, 50, 60};
            如果你给该方法,传入的是一个引用类型数组,那么他会取出数组中的元素,放到集合中
            List<Integer> integers1 = Arrays.asList(integers);
            for (Integer integer : integers1) {
                System.out.println(integer);
            }
            System.out.println("=====================================");
            Integer[] integers2 = {20, 30, 50, 60};
            Integer[] integers3 = {20, 30, 50, 60};
            假如你传入两个以上的数组,他是把数组对象作为元素,放到集合中
            List<Integer[]> integers4 = Arrays.asList(integers, integers2);
            System.out.println(integers4);
            Integer integer = integers4.get(0)[0];
            System.out.println(integer);
            
            System.out.println("================");
            Integer[] integers5 = {20, 30, 50, 60};
            List<Integer> integers6 = Arrays.asList(integers5);
    
            int[] ints = {20, 30, 50, 60};
            当你传人一个基本类型数组,那么转换成集合,集合放到是数组对象(数组对象的指针)
            List<int[]> ints1 = Arrays.asList(ints);
            int[] ints2 = ints1.get(0);
    
            int[] ints3 = {20, 30, 50, 60};
            int[] ints4 = {20, 30, 50, 60};
            List<int[]> ints8 = Arrays.asList(ints3, ints4);
            System.out.println(ints8);
    
            List<Integer> integers7 = Arrays.asList(20, 30, 50, 30, 80); //自动装箱!
    		System.out.println(integers7);
        }
    }
    ------
    输出:
    20
    30
    50
    60
    =====================================
    [[Ljava.lang.Integer;@1b6d3586, [Ljava.lang.Integer;@4554617c]
    20(0个元素)
    ================
    [[I@74a14482, [I@1540e19d](List中存储的是int[]对象的地址值!)
    [20, 30, 50, 30, 80]
    
  • 特别注意:得到的集合长度是不可变的。你不能往这个转换后的集合中添加元素(add)和删除元素(remove),只能获取元素(get)。
JAVA 嵌套集合:(ArrayList嵌套ArrayList)
  • 示例:
    public class MyTest3 {
        public static void main(String[] args) {
            ArrayList<Student> javaList = new ArrayList<>();
            javaList.add(new Student("周丹", 19));
            javaList.add(new Student("周颖", 19));
            javaList.add(new Student("苏沅湘", 20));
            javaList.add(new Student("崔继宣", 19));
    
    
            ArrayList<Student> webList = new ArrayList<>();
    
            webList.add(new Student("周丹1", 19));
            webList.add(new Student("周颖1", 19));
            webList.add(new Student("苏沅湘1", 20));
            webList.add(new Student("崔继宣1", 19));
    
    
            ArrayList<Student> linuxList = new ArrayList<>();
    
            linuxList.add(new Student("周丹2", 19));
            linuxList.add(new Student("周颖2", 19));
            linuxList.add(new Student("苏沅湘2", 20));
            linuxList.add(new Student("崔继宣2", 19));
    
            //我站在西开的角度,我要存储这个三个班(嵌套ArrayList存储)
            ArrayList<ArrayList<Student>> westosList = new ArrayList<>();
            westosList.add(javaList);
            westosList.add(webList);
            westosList.add(linuxList);
           
            //遍历每一个班的每一个学生的信息 二维集合的遍历
            //普通for循环遍历
            for (int i = 0; i < westosList.size(); i++) {
                ArrayList<Student> minList = westosList.get(i);
                // System.out.println(minList);
                for (int j = 0; j < minList.size(); j++) {
                    Student student = minList.get(j);
                    System.out.println(student.getName() + "===" + student.getAge());
                }
            }
            System.out.println("=================================");
            //新式for循环遍历
            for (ArrayList<Student> students : westosList) {
                for (Student student : students) {
                    System.out.println(student.getName() + "===" + student.getAge());
                }
            }
            System.out.println("======================");
        }
    }
    ---------------
    输出:
    周丹===19
    周颖===19
    苏沅湘===20
    崔继宣===19
    周丹1===19
    周颖1===19
    苏沅湘1===20
    崔继宣1===19
    周丹2===19
    周颖2===19
    苏沅湘2===20
    崔继宣2===19
    =================================
    周丹===19
    周颖===19
    苏沅湘===20
    崔继宣===19
    周丹1===19
    周颖1===19
    苏沅湘1===20
    崔继宣1===19
    周丹2===19
    周颖2===19
    苏沅湘2===20
    崔继宣2===19
    ======================
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值