【JAVA基础】17 集合

1. 对象数组的概述和使用

  • 案例演示

    • 需求:我有5个学生,请把这个5个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。

    • package com.heima.collection;
      
      import com.heima.bean.Student;
      
      public class Demo1_Array {
      
          /**
          需求:我有5个学生,请把这个5个学生的信息存储到数组中,并遍历数组,获取得到每一个学生信息。
           */
          public static void main(String[] args) {
              // 创建基本数据类型数组
              int[] arr_base = {1,2,3,4,5};
              
              // 创建引用数据类型数组
              Student[] arr = new Student[5];
              arr[0] = new Student("张三",23);  // 创建一个学生对象,存储在数组的第一个位置
              arr[1] = new Student("李四",24);
              arr[2] = new Student("王五",25);
      
              for(int i = 0; i < arr.length; i++) {
                  System.out.println(arr[i]);
              }
              
          }
      
      }
      View Code
    • package com.heima.bean;
      
      public class Student {
      
          /**
           
           */
          
          private String name;
          private int age;
          
          
          public Student() {
              super();
              
          }
          
          
          public Student(String name, int age) {
              super();
              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 + "]";
          }
          
          
          
      }
      Student类

       

  • 画图演示

    • 把学生数组的案例画图讲解

    • 数组和集合存储引用数据类型,存的都是地址值

 

2. 集合的由来及集合继承体系图

  • 集合的由来

    • 数组长度是固定,当添加的元素超过了数组的长度时需要对数组重新定义。太麻烦!

    • java内部给我们提供了集合类,能存储任意对象,长度是可以改变的,随着元素的增加而增加,随着元素的减少而减少

  • 数组和集合的区别

    • 区别1 :

      • 数组既可以存储基本数据类型,又可以存储引用数据类型。

        • 基本数据类型存储的是值,引用数据类型存储的是地址值

      • 集合只能存储引用数据类型(对象)

        • 集合中也可以存储基本数据类型,但是在存储的时候会自动装箱变成对象

          • 如:存储100,自动装箱,存储new Integer(100);
    • 区别2:

      • 数组长度是固定的,不能自动增长

      • 集合的长度的是可变的,可以根据元素的增加而增长

  • 数组和集合什么时候用

    • 如果元素个数是固定的推荐用数组

    • 如果元素个数不是固定的推荐用集合

  • 集合继承体系图

 

3. Collection集合的基本功能测试

  • 案例演示

    • package com.heima.collection;
      
      import java.util.ArrayList;
      import java.util.Collection;
      
      import com.heima.bean.Student;
      
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public class Demo2_Collection {
      
          /**
           
           */
          public static void main(String[] args) {
              demo1();
              
              demo2();
          }
      
          public static void demo2() {
              Collection c = new ArrayList();
              c.add("a");
              c.add("b");
              c.add("c");
              c.add("d");
              c.remove("b");
              System.out.println(c);
              
              c.remove("e");  // 返回值boolean类型,false,移除失败
              System.out.println(c);
              
              c.clear();  // 清空集合
              System.out.println(c);
              
              System.out.println(c.isEmpty());  // 判断数组集合是否为空
              
              c.add("a");
              System.out.println(c.contains("e"));  // 验证是否包含指定元素
              System.out.println(c.contains("a"));
              
              System.out.println(c.size());  // 获取元素的个数
          
          }
      
          public static void demo1() {
              // Collection是接口,无法实例化
              // 可以通过父类指向子类对象,生成对象,调用Collection的方法
              Collection c = new ArrayList();
              boolean b1 = c.add("abc");  //自动装箱 new String("abc")
              boolean b2 = c.add(true);   // new Boolean(true)
              boolean b3 = c.add(100);    // new Integer(100)
              boolean b4 = c.add(new Student("张三",23));
              boolean b5 = c.add("abc");
              
              
              System.out.println(c);
              /*
               * add方法如果是List集合使用,则一直都返回true,因为List集合是可以存储重复元素的;
               * 如果是Set集合,当存储重复元素的时候,就会返回false
               * 
               * ArrayList的父类的父类,重写了toString方法,所以打印对象的引用的时候,输出的结果不是Object类中的toString的结果
               */
          }
      
      }
      View Code
  • 基本功能演示

    • boolean add(E e)

    • boolean remove(Object o)

    • void clear()

    • boolean contains(Object o)

    • boolean isEmpty()

    • int size()

  • 注意:

    • collectionXxx.java使用了未经检查或不安全的操作。

    • 注意:要了解详细信息,请使用 -Xlint:unchecked重新编译。

    • java编译器认为该程序存在安全隐患

    • 温馨提示:这不是编译失败,所以先不用理会,等学了泛型你就知道了

 

4. 集合的遍历之集合转数组遍历

  • 集合的遍历

    • 其实就是依次获取集合中的每一个元素。

  • 案例演示

    • 把集合转成数组,可以实现集合的遍历

    • package com.heima.collection;
      
      import java.util.ArrayList;
      import java.util.Collection;
      
      import com.heima.bean.Student;
      
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public class Demo3_Collection {
      
          /**
           * @param args
           */
          public static void main(String[] args) {
              demo1();
              
              demo2();
              
          }
      
          public static void demo2() {
              Collection c = new ArrayList();
              c.add(new Student("Ann", 23));  // Object obj = new Student("Ann",23)
              c.add(new Student("Bill", 24));
              c.add(new Student("Caro", 25));
              c.add(new Student("Dai", 26));
              
              Object[] arr = c.toArray();
              
              for(int i = 0; i < arr.length; i++) {
                  System.out.println(arr[i]);
                  //System.out.println(arr[i].getName());
                  /*
                   * Object obj = new Student("Ann",23)
                   * 父类引用指向子类对象
                   * 多态的弊端:不能使用子类特有的属性和行为
                   * 
                   * 类型提升上去了,想要使用Student中的getName和getAge方法, 还需要向下转型
                   */
                  
                  Student s = (Student)arr[i];
                  System.out.println(s.getName() + "," + s.getAge());
              }
          }
      
          public static void demo1() {
              Collection c = new ArrayList();
              c.add("a");
              c.add("b");
              c.add("c");
              c.add("d");
              
              Object[] arr = c.toArray();
              for(int i = 0; i < arr.length; i++) {
                  System.out.println(arr[i]);
              }
          }
      
      }
      View Code

       

5. Collection集合的带All功能测试

  • 带All的功能演示

    • boolean addAll(Collection c)

    • boolean removeAll(Collection c)

    • boolean containsAll(Collection c)

    • boolean retainAll(Collection c)

  • 案例演示
    • package com.heima.collection;
      
      import java.util.ArrayList;
      import java.util.Collection;
      
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public class Demo4_Collection {
      
          /**
           * @param args
           */
          public static void main(String[] args) {
      //        demo1();
      //        demo2();
      //        demo3();
              demo4();
              
              
          }
      
          public static void demo4() {
              /*
               * retainAll 取交集
               * 逻辑:
               * 如果调用的集合改变,则返回true;
               * 如果调用的集合未改变,则返回false。
               * 
               * 如:
               * c1 和 c2的交集是[](空集合),则将[] 赋值给c1,c1的值改变了,返回true;
               * c1 和 c2的交集是[a,b,c,d](和c1一样),则将[a,b,c,d]赋值给c1,c1的值未发生变化,返回false;
               * c1 和 c2的交集是[a,b],则将[a,b] 赋值给c1,c1的值改变了,返回true;
               */
              Collection c1 = new ArrayList();
              c1.add("a");
              c1.add("b");
              c1.add("c");
              c1.add("d");
              
              
      //        Collection c2 = new ArrayList();
      //        c2.add("a");
      //        c2.add("b");
              
              Collection c3 = new ArrayList();
              c3.add("a");
              c3.add("b");
              c3.add("f");
              
              Collection c4 = new ArrayList();
              c4.add("f");
              
              //System.out.println(c1.retainAll(c2));  // 取交集
              System.out.println(c1);  // 输出  [a, b]
              System.out.println(c1.retainAll(c3));  //false
              System.out.println(c1);
              System.out.println(c1.retainAll(c4));   //true
              System.out.println(c1);
          }
      
          public static void demo3() {
              Collection c1 = new ArrayList();
              c1.add("a");
              c1.add("b");
              c1.add("c");
              c1.add("d");
              
              
              Collection c2 = new ArrayList();
              c2.add("a");
              c2.add("b");
              
              Collection c3 = new ArrayList();
              c3.add("a");
              c3.add("b");
              c3.add("f");
              
              System.out.println(c1.containsAll(c2));
              System.out.println(c1.containsAll(c3));
          }
      
          public static void demo2() {
              Collection c1 = new ArrayList();
              c1.add("a");
              c1.add("b");
              c1.add("c");
              c1.add("d");
              
              
              Collection c2 = new ArrayList();
              c2.add("a");
              c2.add("b");
              c2.add("f");
              
              Collection c3 = new ArrayList();
              c3.add("m");
              c3.add("n");
              c3.add("f");
              
              System.out.println(c1.removeAll(c2));  //删除的是c1和c2的交集
              System.out.println(c1);
              
              System.out.println(c1.removeAll(c3));  //若没有交集,则返回false
              System.out.println(c1);
          }
      
          public static void demo1() {
              Collection c1 = new ArrayList();
              c1.add("a");
              c1.add("b");
              c1.add("c");
              c1.add("d");
              
              
              Collection c2 = new ArrayList();
              c2.add("a");
              c2.add("b");
              c2.add("c");
              c2.add("d");
              
              c1.addAll(c2);
              System.out.println(c1);  // 输出[a, b, c, d, a, b, c, d]
              
              c1.add(c2);
              System.out.println(c1);  // 输出[a, b, c, d, a, b, c, d, [a, b, c, d]]
          }
      
      }
      View Code

6. 集合的遍历之迭代器遍历

  • 迭代器概述

    • 集合是用来存储元素,存储的元素需要查看,那么就需要迭代(遍历)

  • 案例演示

    • Iterator<E> iterator()    返回在此 collection 的元素上进行迭代的迭代器。
    • 迭代器的使用

      • package com.heima.collection;
        
        import java.util.ArrayList;
        import java.util.Collection;
        import java.util.Iterator;
        
        import com.heima.bean.Student;
        
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public class Demo5_Iterator {
        
            /**
             * @param args
             */
            public static void main(String[] args) {
        //        demo1();
                
                demo2();
                
                
            }
        
            public static void demo2() {
                Collection c = new ArrayList();
                c.add(new Student("Ann", 23));  // Object obj = new Student("Ann",23)
                c.add(new Student("Bill", 24));
                c.add(new Student("Caro", 25));
                c.add(new Student("Dai", 26));
                
                Iterator it = c.iterator();
                while(it.hasNext()) {
                    Student s = (Student)it.next();
                    System.out.println(s.getName());
                }
            }
        
            public static void demo1() {
                Collection c = new ArrayList();
                c.add("a");
                c.add("b");
                c.add("c");
                c.add("d");
                
                Iterator it = c.iterator();
                while(it.hasNext()) {
                    System.out.println(it.next());
                }
            }
        }
        View Code

         

7. 迭代器的原理及源码解析

  • 迭代器原理

    • 迭代器是对集合进行遍历,而每一个集合内部的存储结构都是不同的,所以每一个集合存和取都是不一样,那么就需要在每一个类中定义hasNext()和next()方法,这样做是可以的,但是会让整个集合体系过于臃肿。

    • 迭代器是将这样的方法向上抽取出接口,然后在每个类的内部,定义自己迭代方式。

    • 这样做的好处有二:

      • 第一规定了整个集合体系的遍历方式都是hasNext()和next()方法

      • 第二,代码有底层内部实现,使用者不用管怎么实现的,会用即可

  • 迭代器源码解析

    • 在eclipse中  ctrl + shift + t  找到ArrayList类

    • ctrl+o查找iterator()方法

    • 查看返回值类型是new Itr(),说明 Itr 这个类实现Iterator接口

    • 查找Itr这个内部类,发现重写了Iterator中的所有抽象方法

 

8. List集合的特有功能概述和测试

  • List的概述
    • 有序的Collection 也称为 序列。
    • 此接口的用户可以对列表中每个元素的插入位置进行精确地控制。
    • 用户可以根据元素的整数索引访问元素,并搜索列表中的元素。
    • List允许重复的元素。
  • List接口提供了4种对元素进行定位(索引)访问方法
    • 所以从0开始
    • 在列表元素上迭代通常优于用索引遍历列表
  • List接口提供了特殊的迭代器,称为ListIterator
    • 除了允许Iterator接口提供的正常操作外
    • 还允许元素插入 和 替换,以及双向访问
    • 还提供了一个方法来获取从列表中指定位置开始的列表迭代器
  • List集合的特有功能概述

    • void add(int index,E element)

    • E remove(int index)

    • E get(int index)

    • E set(int index,E element)

    • package com.heima.list;
      
      import java.util.ArrayList;
      import java.util.List;
      
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public class Demo1_List {
      
          /**
          
           */
          public static void main(String[] args) {
      //        demo1();
      //        demo2();
              
      //        demo3();
      //        demo4();
          }
      
          public static void demo4() {
              /* E get(int index) 
                  返回列表中指定位置的元素。 */
              List list = new ArrayList();
              list.add("a");
              list.add(1);
              list.add(2);
              list.add("big");
              System.out.println(list.set(0, "set a new value"));
              System.out.println(list);
              
          }
          
          public static void demo3() {
              /* E get(int index) 
                  返回列表中指定位置的元素。 */
              List list = new ArrayList();
              list.add("a");
              list.add(1);
              list.add(2);
              list.add("big");
              System.out.println(list.get(0));
              
              // 通过索引遍历
              for(int i = 0;i < list.size(); i++) {
                  System.out.println(list.get(i));
              }
              
          }
      
          public static void demo2() {
               /*
                * E remove(int index) 
                *     移除列表中指定位置的元素(可选操作)。 
                * boolean remove(Object o) 
                *     从此列表中移除第一次出现的指定元素(如果存在)(可选操作)。 
               */
              List list = new ArrayList();
              list.add("A");
              list.add(1);
              list.add(2);
              System.out.println(list);
              list.remove(1);
              System.out.println(list);
          }
          
          public static void demo1() {
               /*
                * boolean add(E e) 
                * 向列表的尾部添加指定的元素(可选操作)。
                * 
                *  void add(int index, E element) 
                *  在列表的指定位置插入指定元素(可选操作)。 
               */
              List list = new ArrayList();
              list.add("0");
              System.out.println(list);
              list.add("1");
              list.add("2");
              list.add("3");
              System.out.println(list);
              list.add(3,"add in index 3");
              list.add(list.size(),"last one");
              System.out.println(list);
          }
      }
      View Code

 

9. List集合存储学生对象并遍历

  • 案例演示

    • 通过size()和get()方法结合使用遍历。

    • package com.heima.list;
      
      import java.util.ArrayList;
      import java.util.List;
      
      import com.heima.bean.Student;
      
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public class Demo2_List {
          public static void main(String[] args) {
              List list = new ArrayList(); 
              list.add(new Student("张三", 18)); 
              list.add(new Student("李四", 18)); 
              list.add(new Student("王五", 18)); 
              list.add(new Student("赵六", 18));
      
              for(int i = 0; i < list.size(); i++) {
                  Student s = (Student)list.get(i);
                  System.out.println(s.getName() + "," + s.getAge());
              }
          }
          
          
      }
      View Code

10. 并发修改异常产生的原因及解决方案

  • 案例演示

    • 需求:我有一个集合,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。

    • package com.heima.list;
      
      import java.util.ArrayList;
      import java.util.Iterator;
      import java.util.List;
      
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public class Demo3_List {
      
          /**
           需求:我有一个集合,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
           */
          public static void main(String[] args) {
              List list = new ArrayList(); 
              list.add("a"); 
              list.add("b"); 
              list.add("world"); 
              list.add("d"); 
              list.add("e");
              
              Iterator it = list.iterator();
              while(it.hasNext()){
                  String str = (String)it.next();
                  if(str.equals("world")) {
                      list.add("javaee");  
                      //这里会抛出ConcurrentModificationException 并发修改异常
                  }
              }
      
          
          }
      
      }
      View Code
  • ConcurrentModificationException出现

    • 迭代器遍历,集合修改集合

    • 因为遍历的同时,list在添加元素,这就是 并发修改异常
  • 解决方案

    • 迭代器迭代元素,迭代器修改元素(ListIterator的特有功能add)

    • 集合遍历元素,集合修改元素

    • package com.heima.list;
      
      import java.util.ArrayList;
      import java.util.List;
      import java.util.ListIterator;
      
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public class Demo3_List {
      
          /**
           需求:我有一个集合,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
           */
          public static void main(String[] args) {
              List list = new ArrayList(); 
              list.add("a"); 
              list.add("b"); 
              list.add("world"); 
              list.add("d"); 
              list.add("e");
              
              ListIterator lit = list.listIterator(); 
              //如果想在遍历的过程中添加元素,可以用ListIterator中的add方法 
              while(lit.hasNext()) { 
                  String str = (String)lit.next(); 
                  if(str.equals("world")) { 
                      lit.add("javaee"); 
                      // 输出[a, b, world, javaee, d, e]
      
                      //list.add("javaee"); } }
                  }
              }
              
              System.out.println(list);
              
          
          }
      
      }
      View Code

 

11. ListIterator

  • boolean hasNext()   是否有下一个

  • boolean hasPrevious()   是否有前一个

  • Object next()    返回下一个元素

  • Object previous()    返回上一个元素

  • package com.heima.list;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.ListIterator;
    
    public class Demo4_ListIterator {
    
        /**
         * @param args
         */
        public static void main(String[] args) {
            List list = new ArrayList();
            list.add("a");                                    //Object obj = new String();
            list.add("b");
            list.add("world");
            list.add("c");
            list.add("d");
            list.add("e");
            
            ListIterator lit = list.listIterator();            //获取迭代器
            while(lit.hasNext()) {
                System.out.println(lit.next());             //迭代器向后
            }
            
            System.out.println("-----------------");
            
            while(lit.hasPrevious()) {
                System.out.println(lit.previous());         //迭代器向前
            }
        }
    
    }
    View Code

 

12. Vector的特有功能

  • Vector类概述

    • Vector类可以实现可增长的对象数组。
    • 与数组一样,它包含可以使用整数索引进行访问的组件。
    • Vector的大小可以根据需要增大或缩小,以适应创建Vector后进行添加或移除项的操作。
    • Vector类是从JDK1.0版本就存在的,后期改进加入List接口,使得成为Java Collections Framework的成员。与新collection实现不同,Vector是同步的。
  • Vector类特有功能

    • public void addElement(E obj)

    • public E elementAt(int index)

    • public Enumeration elements()

  • 案例演示

    • Vector的迭代

    • package com.heima.list;
      
      import java.util.Enumeration;
      import java.util.Vector;
      
      public class Demo5_Vector {
      
          /**
           * @param args
           */
          public static void main(String[] args) {
              Vector v = new Vector();
              v.addElement("a");
              v.addElement("b");
              v.addElement("c");
              v.addElement("d");
              
              Enumeration en = v.elements();                    //获取枚举
              while(en.hasMoreElements()) {                    //判断是否还有元素
                  System.out.println(en.nextElement());        //迭代下一个元素
              }
          }
      
      }
      View Code

 

13. 数据结构之数组和链表

  • 数组

    • 查询快,修改也快

      • 因为有索引,直接找到索引即可
    • 增删慢

      • 数组是固定的大小,新增会新增1.5倍大小的数组,再存储,垃圾回收掉旧的数组
  • 链表

    • 查询慢,修改也慢

      • 只能判断是从头开始找还是从尾巴开始找比较快,一个一个找过去
    • 增删快

 

14. List的三个子类的特点

  • List的三个子类的特点

    • ArrayList: 底层数据结构是数组,查询快,增删慢。 线程不安全,效率高。

    • Vector: 底层数据结构是数组,查询快,增删慢。 线程安全,效率低。

      • Vector相对ArrayList查询慢(线程安全的)

      • Vector相对LinkedList增删慢(数组结构)

    • LinkedList: 底层数据结构是链表,查询慢,增删快。 线程不安全,效率高。

  • Vector 和 ArrayList的区别
    • Vector是线程安全的,效率低
    • ArrayList是线程不安全的,效率高
  • Vecotr 和 ArrayList的共同点
    • 都是数组实现的
  • ArrayList 和 LinkedList 的区别
    • ArrayList底层是数组实现的,查询和修改快
    • LinkedList底层是链表结构的,增删比较快,查询和修改比较慢
  • ArrayList 和 LinkedList 的共同点
    • 都是线程不安全的
  • List有三个儿子,我们到底使用谁呢?

    • 查询多用ArrayList

    • 增删多用LinkedList

    • 如果都多ArrayList

15. 去除ArrayList中重复字符串元素方式

  • 案例演示1
    • 需求:ArrayList去除集合中字符串的重复值(字符串的内容相同)
    • 思路:创建新集合方式
    • package com.heima.list;
      
      import java.util.ArrayList;
      import java.util.List;
      import java.util.ListIterator;
      
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public class Demo2_ArrayList {
      
          public static void main(String[] args) {
              List list = new ArrayList();
              list.add("a");
              list.add("a");
              list.add("b");
              list.add("b");
              list.add("b");
              list.add("c");
              list.add("c");
              list.add("c");
              list.add("c");
              
              System.out.println(list);
              //System.out.println(getSingle(list));
              ArrayList newList = getSingle(list);
              System.out.println(newList);
          }
      
          /*
           * 创建新集合,将重复元素去掉
           * 1. 明确返回值类型,返回ArrayList
           * 2. 明确参数列表, ArrayList
           */
          public static ArrayList getSingle(List list) {
              ListIterator lit = list.listIterator();
              ArrayList newList = new ArrayList();
              while(lit.hasNext()) {
                  Object obj = lit.next();
                  if(!newList.contains(obj)) {
                      newList.add(obj);
                  }
              }
              return newList;
          }
      }
      View Code
  • 案例演示2
    • 需求:ArrayList去除集合中自定义对象元素的重复值(对象的成员变量值相同)
    • 注意事项:重写equals()方法的
    • 参考案例1旧方法出错的原因:
      • newList.contains 的底层依赖Object类中的 equals方法,比较的自定义对象是 比较对象本身,即对象的地址。
      • 想要不出错,则在Person类(自定义类)中重写 equals方法
    • 代码:
      • package com.heima.bean;
        
        public class Person {
            private String name;
            private int age;
            
            public Person() {
                super();
            }
        
            public Person(String name, int age) {
                super();
                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 "Person [name=" + name + ", age=" + age + "]";
            }
        
            @Override
            public boolean equals(Object obj) {
                Person p = (Person)obj;
                return this.name.equals(p.name) && this.age == p.age;
            }
            
            
            
            
        }
        Person类 
        package com.heima.list;
        
        import java.util.ArrayList;
        import java.util.Iterator;
        
        import com.heima.bean.Person;
        
        @SuppressWarnings({ "rawtypes", "unchecked" })
        public class Demo3_ArrayList {
        
            public static void main(String[] args) {
                ArrayList list = new ArrayList();
                list.add(new Person("Ann",23));
                list.add(new Person("Bill",24));
                list.add(new Person("Ann",23));
                list.add(new Person("Bill",24));
                list.add(new Person("Ann",23));
                list.add(new Person("Carolle",25));
                list.add(new Person("Dell",26));
                list.add(new Person("Ann",23));
                list.add(new Person("Carolle",25));
                list.add(new Person("Dell",26));
                
                ArrayList newList = getSingle(list);
                System.out.println(newList);
        
                
                
            }
            
            /*
             * 创建新集合,将重复元素去掉
             * 1. 明确返回值类型,返回ArrayList
             * 2. 明确参数列表, ArrayList
             */
            public static ArrayList getSingle(ArrayList list) {
                Iterator it = list.iterator();
                ArrayList newList = new ArrayList();
                while(it.hasNext()) {
                    Object obj = it.next();
                    if(!newList.contains(obj)) {
                        newList.add(obj);
                    }
                }
                return newList;
            }
        
        }
        View Code

16. LinkedList的特有功能

  • LinkedList类概述
    • List接口的链接列表实现。
    • 实现所有可选的列表操作,并且允许所有元素(包括null)
    • 除了实现List接口外,LinkedList类还为在列表的开头及结尾 get、remove 和insert元素提供了统一的命令方法
    • 这些操作允许将链接列表用作堆栈、队列或双端队列。
  • LinkedList类特有功能
    • public void addFirst(E e)
    • public void addLast(E e)
    • public E getFirst()
    • public E getLast()
    • public E removeFirst()
    • public E removeLast()
    • public E get(int index)
    • package com.heima.list;
      
      import java.util.LinkedList;
      
      @SuppressWarnings({ "rawtypes", "unchecked" })
      public class Demo1_LinkedList {
      
          /**
           * @param args
           */
          public static void main(String[] args) {
              LinkedList lis = new LinkedList();
              
              System.out.println("----addXxx方法----");
              lis.addFirst("a");
              lis.addFirst("b");
              lis.addFirst("c");
              lis.addFirst("d");
              lis.addLast("e");
              
              System.out.println(lis);
              
              System.out.println("----getXxx方法----");
              System.out.println(lis.getFirst());
              System.out.println(lis.getLast());
              
              System.out.println("----removeXxx方法----");
              lis.removeFirst();
              System.out.println(lis.getFirst());
              lis.removeLast();
              System.out.println(lis.getLast());
              
              System.out.println("----get方法----");
              System.out.println(lis);
              System.out.println(lis.get(0));  // 通过查看源码,发现是通过判断index值是否大于size的一半,离哪边近,选择从头或从末尾开始找
              System.out.println(lis.get(1));
              System.out.println(lis.get(2));
          }
      
      }
      View Code

17. 栈和队列数据结构

    • 先进后出
  • 队列
    • 先进先出

18. 用LinkedList模拟栈数据结构的集合并测试

  • 案例演示
    • 需求:请用LinkedList模拟栈数据结构的集合,并测试

    • 创建一个类将LinkedList中的方法封装

    • package com.heima.list;
      
      import java.util.LinkedList;
      
      public class Stack {
          private LinkedList list = new LinkedList(); 
          
          /* 
           * 模拟进栈方法
           */
          public void in(Object obj) {
              list.addLast(obj);
          }
          
          /*
           * 模拟出栈
           */
          public Object out() {
              return list.removeLast();
          }
          
          /*
           * 模拟栈结构是否为空
           */
          public boolean isEmpty() {
              return list.isEmpty();
          }
      
          @Override
          public String toString() {
              return "Stack [list=" + list + "]";
          }
          
          
      }
      封装LinkedList类,变成Stack类
      package com.heima.list;
      
      import java.util.LinkedList;
      
      @SuppressWarnings({"rawtypes","unchecked"})
      public class Demo2_LinkedList {
      
          /**
           用LinkedList模拟 栈数据 结构的集合,并测试
           */
          public static void main(String[] args) {
      //        demo1();
              Stack s = new Stack();
              s.in("a");   // 进栈
              s.in("b");
              s.in("c");
              
              while(!s.isEmpty()) {
                  System.out.println(s.out());  // 弹栈
              }
              System.out.println(s.toString());
          }
      
          public static void demo1() {
              LinkedList lis = new LinkedList();  //创建集合对象
              
              lis.addLast("a");
              lis.addLast("b");
              lis.addLast("c");
              
              while(!lis.isEmpty()) {
                  System.out.println(lis.removeLast());
              }
          }
      
      }
      演示

19. 泛型概述和基本使用

  • 泛型概述

    • 泛型,即“参数化类型”。
    • 将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称为类型形参),然后在使用/调用时传入具体的类型(类型实参)
    • 泛型的本质是为了参数化类型(在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型),即,在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类、接口和方法中,分别被称为“泛型类”,“泛型接口”,“泛型方法”
  • 泛型好处

    • 提高安全性(将运行期的错误转换到编译期)

    • 省去强转的麻烦

  • 泛型基本使用

    • <> 中放的必须是引用数据类型

  • 泛型使用注意事项

    • 前后的泛型必须一致

    • 或者后面的泛型可以省略不写(1.7版本的新特性)

  • package com.heima.generic;
    
    import java.util.ArrayList;
    import java.util.Iterator;
    
    import com.heima.bean.Person;
    
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public class Demo1_Generic {
    
        /**
         
         */
        public static void main(String[] args) {
    //        demo1();
            
    //        int[] arr = new byte[5];  // 数组要保证前后的数据类型一致
    //        ArrayList<Object> list = new ArrayList<Person>(); // 集合的泛型,要保证前后的数据类型一致
            ArrayList<Object> list = new ArrayList<>();  //1.7 版本新特性,后面的泛型可以不写
            
            /*
             * 泛型最好不要定义成Object,因为泛型可以支持其指定类型及其所有的子类。
             * Object作为所有类的父类,没有意义。
             */
            list.add(100);
            list.add("s");
            list.add(true);
        }
    
        public static void demo1() {
            ArrayList<Person> list = new ArrayList<Person>();
    //        list.add(110);
    //        list.add(true);
            list.add(new Person("Ann",23));
            
            Iterator<Person> it = list.iterator();
            while(it.hasNext()) {
                
                Person p = it.next();
                System.out.println(p);
            }
        }
    
    }
    View Code

 

20. ArrayList存储字符串和自定义对象并遍历泛型版

  • 案例演示

    • ArrayList存储字符串并遍历泛型版

    • package com.heima.generic;
      
      import java.util.ArrayList;
      import java.util.Iterator;
      
      public class Demo2_Generic {
      
          /**
          需求:ArrayList存储字符串并遍历泛型版
           */
          public static void main(String[] args) {
              ArrayList<String> list = new ArrayList<String>();
              list.add("a");
              list.add("123");
              list.add("111");
              
              Iterator<String> it = list.iterator();
              while(it.hasNext()) {
                  System.out.println(it.next());
              }
              
          }
      
      }
      View Code

21. 泛型的由来

  • 案例演示

    • 泛型的由来:通过Object转型问题引入

    • 早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。

    • package com.heima.generic;
      
      import com.heima.bean.Student;
      import com.heima.bean.Tool;
      import com.heima.bean.Worker;
      
      public class Demo3_Generic {
      
          /**
           
           */
          public static void main(String[] args) {
              Tool t = new Tool();  // 创建工具类对象
              t.setObj(new Student());
              
              t.setObj(new Student("Ann",23));
              
      
      //        Worker w = (Worker) t.getObj(); //向下转型
              // ClassCastException 报错,t里面getObj()获取的是Student类的向上转型Person类  Person [name=Ann, age=23]
      //        System.out.println(w);
          }
      
      }
      View Code
    • package com.heima.bean;
      
      public class Tool {
          private Object obj;
      
          public Tool() {
              super();
              
          }
      
          public Tool(Object obj) {
              super();
              this.obj = obj;
          }
      
          public Object getObj() {
              return obj;
          }
      
          public void setObj(Object obj) {
              this.obj = obj;
          }
          
          
      }
      Tool类
    • package com.heima.bean;
      
      public class Person {
          private String name;
          private int age;
          public Person() {
              super();
              
          }
          public Person(String name, int age) {
              super();
              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 "Person [name=" + name + ", age=" + age + "]";
          }
          @Override
          public boolean equals(Object obj) {
              Person p = (Person)obj;
              //return super.equals(obj);
              return this.name.equals(p.name) && this.age == p.age;
          }
          
          
          
      }
      Person类
    • package com.heima.bean;
      
      public class Student extends Person {
      
          public Student() {
          }
      
          public Student(String name, int age) {
              super(name, age);
      
          }
      
      }
      Student类
    • Worker类

22. 泛型类的概述及使用

  • 泛型类概述<T>

    • 把泛型定义在类上

    • package com.heima.bean;
      
      public class Tool<E> {
          private E e;
      
          public Tool() {
              super();
              
          }
      
          public Tool(E e) {
              super();
              this.e = e;
          }
      
          public E getObj() {
              return e;
          }
      
          public void setObj(E e) {
              this.e = e;
          }
          
          public void show(E e) {
              System.out.println(e);
          }
          
      }
      View Code
  • 定义格式

    • public class 类名<泛型类型1,…>

  • 注意事项

    • 泛型类型必须是引用类型

  • 案例演示

    • 泛型类的使用

 

23. 泛型方法的概述和使用

  • 泛型方法概述

    • 把泛型定义在方法上

  • 定义格式

    • public <泛型类型> 返回类型 方法名(泛型类型 变量名)

    • 方法泛型需要与类的泛型一致
      • public class Tool<E>
      • public void show(E e)  类的泛型为E,如果方法不重新定义泛型,则需要与类泛型一致
    • 如果方法泛型要和类的泛型不一致,需要在方法上声明一个新的泛型
      • public<T> void show(T t)
      • 相当于给方法定义了一个新的泛型
    • 静态方法必须要声明一个自己的泛型
      • public static<W> void print(W w)
  • 案例演示

    • 泛型方法的使用

    • package com.heima.bean;
      
      public class Tool<E> {
          private E e;
      
          public Tool() {
              super();
              
          }
      
          public Tool(E e) {
              super();
              this.e = e;
          }
      
          public E getObj() {
              return e;
          }
      
          public void setObj(E e) {
              this.e = e;
          }
          
          public void show(E e) {
              System.out.println(e);
          }
          
          // 静态方法必须声明一个自己的泛型
          public static<W> void print(W w) {
              System.out.println(w);
          }
      }
      View Code

 

24. 泛型接口的概述和使用

  • 泛型接口概述

    • 把泛型定义在接口上

  • 定义格式

    • public interface 接口名<泛型类型>

  • 案例演示

    • 泛型接口的使用

    • package com.heima.generic;
      
      public class Demo4_Generic {
      
          /**
           * @param args
           */
          public static void main(String[] args) {
      
          }
      
      }
      
      interface Inter<T> {
          public void show(T t);
      }
      
      // 第一种:接口泛型的使用方法,推荐
      class Demo implements Inter<String> {
      
          @Override
          public void show(String t) {
              System.out.println(t);
          }
          
      }
      
      // 第二种:接口泛型的使用方法
      // 没有必要在实现接口泛型的时候,还要给自己类加一个泛型
      class Demo2<T> implements Inter<T> {
      
          @Override
          public void show(T t) {
          }
          
      }
      View Code

 

25. 泛型高级之通配符

  • 泛型通配符<?>

    • 任意类型,如果没有明确,那么就是Object以及任意的Java类了

  • ? extends E

    • 向下限定,E及其子类

    • package com.heima.generic;
      
      import java.util.ArrayList;
      import java.util.Collection;
      import java.util.List;
      
      import com.heima.bean.Person;
      import com.heima.bean.Student;
      
      public class Demo5_Generic {
          
          /*
           * 泛型通配符<?>
           *         任意类型,如果没有明确,那么就是Object以及任意的Java类了
           * ? extends E
           *         向下限定,E及其子类
           * ? super E
           *         向上限定,E及其父类
           */
          public static void main(String[] args) {
      //        demo1();
              
      //        demo2();
              
              
          }
      
          public static void demo2() {
              ArrayList<Person> list1 = new ArrayList<>();
              list1.add(new Person("Ann",23));
              list1.add(new Person("Bill",24));
              list1.add(new Person("Carolle",25));
              list1.add(new Person("Dell",26));
              
              ArrayList<Student> list2 = new ArrayList<>();
              list2.add(new Student("stu1",18));
              list2.add(new Student("stu2",17));
              
              list1.addAll(list2);  //  public boolean addAll(Collection<? extends E> c) 
              System.out.println(list1);
          }
      
          public static void demo1() {
              List<?> list = new ArrayList<String>();
              // 当右边的泛型是不确定时,那么左边可以指定为"?"
          }
      
      }
      View Code
  • ? super E

    • 向上限定,E及其父类

 

26. 增强for的概述和使用

  • 增强for概述

    • 简化数组和Collection集合的遍历

  • 格式:

    • for(元素数据类型 变量 : 数组或者Collection集合) { 使用变量即可,该变量就是元素 }

    • for (int i : arr) {}
  • 案例演示

    • 数组,集合存储元素用增强for遍历

    • package com.heima.jdk5;
      
      import java.util.ArrayList;
      
      public class Demo1_Foreach {
      
          /**
           * @param args
           */
          public static void main(String[] args) {
      
              int[] arr = {11,22,33,44,55};
              // fore + alt + / 快捷键生成
              // 会找到离它最近的集合或数组,生成代码块
              for (int i : arr) {
                  System.out.println(i);
              }
              
              ArrayList<String> list = new ArrayList<>();
              list.add("a");
              list.add("b");
              list.add("c");
              list.add("d");
              
              for (String string : list) {
                  System.out.println(string);
              }
              
              
              
          }
      
      }
      View Code
  • 好处

    • 简化遍历

 

27. ArrayList存储字符串和自定义对象并遍历增强for版

  • 案例演示

    • ArrayList存储字符串并遍历增强for版

      • package com.heima.jdk5;
        
        import java.util.ArrayList;
        
        public class Demo2_Foreach {
        
            /**
            需求:ArrayList存储字符串并遍历增强for版
            */
            public static void main(String[] args) {
                ArrayList<String> list = new ArrayList<>(); 
                list.add("a"); 
                list.add("b"); 
                list.add("c"); 
                list.add("d");
        
                for(String s : list) {
                    System.out.println(s);
                }
            }
        
        }
        View Code
    • ArrayList存储自定义对象并遍历增强for板
      • package com.heima.jdk5;
        
        import java.util.ArrayList;
        
        import com.heima.bean.Person;
        
        public class Demo2_Foreach {
        
            /**
            需求:ArrayList存储字符串并遍历增强for版
            */
            public static void main(String[] args) {
                ArrayList<Person> list = new ArrayList<>(); 
                list.add(new Person("Ann",23));
                list.add(new Person("Bill",24));
                list.add(new Person("Carolle",23));
                list.add(new Person("Dell",29));
                list.add(new Person("Ella",30));
                
                for (Person person : list) {
                    System.out.println(person);
                }
        
                
            }
        
        }
        View Code
      • 增强for循环底层依赖的是迭代器(Iterator)

 

28. 三种迭代的能否删除

  • 普通for循环,可以删除,但是索引要--

  • 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常

  • 增强for循环不能删除

package com.heima.jdk5;

import java.util.ArrayList;
import java.util.Iterator;

public class Demo3_Foreach {

    /**
     1. 普通for循环,可以删除,但是索引要--,即:i--
     2. 迭代器,可以删除,但是必须使用迭代器自身的remove方法,否则会出现并发修改异常
     3. 增强for循环不能删除
     */
    public static void main(String[] args) {
//        demo1();
        
//        demo2();
        
        demo3();
        
        
    }

    public static void demo3() {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("b");
        list.add("d");
        
        for (String string : list) {
            if("b".equals(string)) {
                // 增强for循环,不能删除,只能遍历
            }
            
        }
    }

    public static void demo2() {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("b");
        list.add("d");
        
        // 迭代器遍历
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            /*it.next();
            it.remove();*/
            if("b".equals(it.next())) {
                it.remove();
//                list.remove("b");// 不能用集合的remove方法,会出现并发修改异常
            }
        }
        System.out.println(list);
        
        for(Iterator<String> it2 = list.iterator();it.hasNext();) {
            if("b".equals(it2.next())) {
                it2.remove();
            }
        }
        System.out.println(list);
    }

    public static void demo1() {
        ArrayList<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("b");
        list.add("c");
        list.add("b");
        list.add("d");
        
        // 第一种,普通for循环删除
        /*for(int i = 0; i < list.size(); i++) {
            list.remove(i);
            i--;
        }
        System.out.println(list);*/
        
        // 第一种,普通for循环删除,条件判断
        for(int i = 0; i < list.size(); i++) {
            if("b".equals(list.get(i))) {
                list.remove(i);
                i--;
            }
        }
        System.out.println(list);
    }

}
View Code

29. 静态导入的概述和使用

  • 静态导入概述

    • 导入包中的静态方法
    • 在开发中一般是不用的
  • 格式:

    • import static 包名….类名.方法名;

    • 可以直接导入到方法的级别

  • 注意事项

    • 方法必须是静态的,如果有多个同名的静态方法,容易不知道使用谁?

    • 这个时候要使用,必须加前缀。

    • 由此可见,意义不大,所以一般不用,但是要能看懂。

  • 示例
    • package com.heima.list;
      
      import static java.util.Arrays.sort;
      
      public class Demo3_Static {
          public static void main(String[] args) {
              int[] arr = {11,44,5,56,77,99,10};
              sort(arr);
              /*
               * 缺点:
               * 容易对同名方法,不知道调用哪个
               */
          }
      }
      View Code

 

30. 可变参数的概述和使用

  • 可变参数概述

    • 定义方法的时候不知道该定义多少个参数

  • 格式

    • 修饰符 返回值类型 方法名(数据类型… 变量名){}

    • public static void func(int ... arr) {}
    • package com.heima.jdk5;
      
      public class Demo4_ChangeableArgs {
      
          /**
           * @param args
           */
          public static void main(String[] args) {
              int[] arr = {11,22,33,44,55};
              print(11, arr);
              print(1,2,3,4,5); // 将1,2,3,4,5封装成了一个 数组
          }
          
          /*public static void print(int[] arr) {
              for (int i : arr) {
                  System.out.println(i);
              }
          }
          */
          public static void print(int x , int ... arr) {  // 可变参数其实就是一个数组
              for (int i : arr) {
                  System.out.println(i);
              }
          }
      
      }
      View Code
  • 注意事项:

    • 这里的变量其实是一个数组

    • 如果一个方法有可变参数,并且有多个参数,那么,可变参数肯定是最后一个

 

31. Arrays工具类的asList()方法的使用

  • static<T> List<T> asList(T ... a)  返回一个受指定数组支持的固定大小的列表
  • 案例演示

    • Arrays工具类的asList()方法的使用

      • package com.heima.jdk5;
        
        import java.util.Arrays;
        import java.util.List;
        
        public class Demo5_asList {
        
            /**
             * static <T> List<T> asList(T... a) 返回一个受指定数组支持的固定大小的列表。 
             * 数组转换成集合
             * 虽然不能增加或减少元素,但是可以用集合的思想操作数组,也就是说可以使用其他集合中的方法(除add和remove方法)
             */
            public static void main(String[] args) {
        //        demo1();
                
                int[] arr = {1,2,3,4,5};
                List list = Arrays.asList(arr);
                System.out.println(list); // 输出[[I@1813c12]
                
                List<int[]> list2 = Arrays.asList(arr);
                System.out.println(list2);  // 输出[[I@1813c12]
                // 上述arr中由于存储的是基本数据类型int,而List存储的是引用数据类型,故默认将整个数组作为一个对象,存储在List中
                
                
                // 如果想要将arr中的每个数字变成Integer,逐个存储到List中去
                Integer[] arr2 = {1,2,3,4,5};
                List<Integer> list3 = Arrays.asList(arr2);
                System.out.println(list3);  // 输出[1, 2, 3, 4, 5]
                
                
            }
        
            public static void demo1() {
                String[] arr = {"a","b","c","d"};
                List<String> list = Arrays.asList(arr);  // 将数组转换成集合
                System.out.println(list);
                // list.add("aaa");  // java.lang.UnsupportedOperationException
            }
        
        }
        View Code
      • 将数组转换成集合,数组必须是引用数据类型
    • Collection中toArray(T[] a)泛型版的集合转数组

      • package com.heima.list;
        
        import java.util.ArrayList;
        
        public class Demo4_Collection {
            /*
             *  Object[] toArray() 
             *      返回包含此 collection 中所有元素的数组。 
             *  <T> T[] toArray(T[] a) 
             *      返回包含此 collection 中所有元素的数组;返回数组的运行时类型与指定数组的运行时类型相同。 
             */
            public static void main(String[] args) {
                ArrayList<String> list = new ArrayList<>();
                list.add("a");
                list.add("b");
                list.add("c");
                list.add("d");
                list.add("e");
                
                // 将集合转成数组
                String[] arr = list.toArray(new String[0]);
                // 当集合转换数组时,数组的长度如果是小于等于集合的size时,转换后的数组长度等于集合的size;
                // 数组的长度如果大于集合的size时,转换后的数组长度为指定长度,且超出部分为null
                for (String string : arr) {
                    System.out.println(string);
                }
            }
        }
        View Code

 

32. 集合嵌套之ArrayList嵌套ArrayList

  • 案例演示

    • 集合嵌套之ArrayList嵌套ArrayList

    • package com.heima.list;
      
      import java.util.ArrayList;
      
      import com.heima.bean.Person;
      
      public class Demo5_ArrayList {
      
          /**
           集合嵌套之ArrayList嵌套ArrayList
           */
          public static void main(String[] args) {
              ArrayList<ArrayList<Person>> list = new ArrayList<>();
              ArrayList<Person> first = new ArrayList<>(); // 创建第一个班级
              first.add(new Person("Ann",23));
              first.add(new Person("Bill",24));
              first.add(new Person("Carolle",25));
              
              ArrayList<Person> second = new ArrayList<>();
              second.add(new Person("张三",23));
              second.add(new Person("李四",24));
              second.add(new Person("王五",25));
              
              // 将班级添加到学科集合中
              list.add(first);
              list.add(second);
              
              // 遍历学科集合
              for(ArrayList<Person> a: list) {
                  for (Person person : a) {
                      System.out.println(person);
                  }
              }
              
          }
      
      }
      View Code
原文地址:https://www.cnblogs.com/zoe233/p/12887465.html