• javaday18_ArrayList


    第一章:ArrayList:

    ArrayList介绍:

    ArrayList存储元素:

     1 package cn.zcb.demo01;
     2 
     3 import java.util.ArrayList;
     4 
     5 public class Test {
     6     /*
     7      * ArrayList 中是不装基础类型的
     8      * */
     9     public static void main(String[] args) {
    10         ArrayList <Integer> arrayList = new ArrayList<Integer>();
    11         arrayList.add(12);
    12         arrayList.add(13);
    13         arrayList.add(14);
    14         arrayList.add(15);
    15 
    16         //遍历
    17         for (int i =0;i<arrayList.size();i++){
    18             System.out.println(arrayList.get(i));
    19         }
    20 
    21     }
    22 }
    View Code

    下面是存储自定义的数据类型:

     1 package cn.zcb.demo01;
     2 
     3 public class Person {
     4 
     5     private String name;
     6     private int age;
     7 
     8     public Person(){} //空参
     9     public Person(String name,int age){ //满参
    10         super();
    11         this.name = name;
    12         this.age = age;
    13     }
    14     //重写 toString() 方法,使print() 的时候不打印内存地址
    15     public String toString(){
    16         return String.format("Person [name:%s age:%d]", name,age);
    17     }
    18     public void setName(String name){
    19         this.name = name;
    20     }
    21     public void setAge(int age){
    22         this.age = age;
    23     }
    24     public String getName(){
    25         return this.name;
    26     }
    27     public int getAge(){
    28         return this.age;
    29     }
    30 }
    Person.java
     1 package cn.zcb.demo01;
     2 
     3 import java.util.ArrayList;
     4 
     5 public class Test {
     6     public static void main(String[] args) {
     7         ArrayList<Person> arrayList = new ArrayList<Person>();
     8         arrayList.add(new Person("tom",18));
     9         arrayList.add(new Person("egon",28));
    10         arrayList.add(new Person("jane",38));
    11 
    12         //遍历
    13         for (int i=0;i<arrayList.size();i++){
    14             System.out.println(arrayList.get(i));
    15         }
    16 
    17     }
    18 }
    19 /* 输出结果
    20 Person [name:tom age:18]
    21 Person [name:egon age:28]
    22 Person [name:jane age:38]
    23 * */
    Test.java

    注意Person中的toString() 被重写了。

    学习一个容器,我们有三个方面:

    1,会存储对象

    2,会遍历,取出对象

    3,它自己所具有的特性!

    ArrayList的  继承 实现关系:

     

     

    Collection接口 的学习:

    但是,list和 set 是有共同点的,就是 Collection接口

     

    Collection接口 的基本方法:

    因为ArrayList 类  实现了 List  接口,而List 接口又继承自 Collection接口。所以,ArrayList 是Collection 的实现类!!! 

    我们下面通过实现类的重写方法来 学习Collection 中的基本方法!

    穿插总结:

     1 package cn.zcb.demo01;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Collection;
     5 
     6 public class Test {
     7     public static void main(String[] args) {
     8 
     9         //以多态的形式调用
    10         Collection <String> collection = new ArrayList<>();
    11         collection.add("a");
    12         collection.add("dfj");
    13         collection.add("i");
    14         System.out.println(collection);  //根据输出结果可以推测,ArrayList 中重写了toString() !!!
    15         /*输出:
    16         *[a, dfj, i]
    17         * */ //它表明ArrayList 是有序的。
    18 
    19         collection.clear(); //此时的集合只是为空[ ],而不是释放!
    20 
    21         /*
    22         * contains ()  方法
    23         * boolean contains(Object obj); 注意参数是 Object obj  产生了多态!!!
    24         * */
    25         boolean ret = collection.contains("a");
    26         System.out.println(ret);  //false
    27 
    28         collection.add("tom");
    29         ret = collection.contains("egon");
    30         System.out.println(ret); //false
    31         ret = collection.contains("tom");
    32         System.out.println(ret); //true
    33 
    34         collection.add("alex");
    35         System.out.println(collection);
    36         //输出: [tom,alex]
    37 
    38         /*
    39         * toArray() 方法
    40         * 转成一个数组。 数组类型是 Object []
    41         * */
    42 //        String[] res =  collection.toArray(); //错误!!
    43         Object[] res =  collection.toArray();
    44         //此时res 就是个数组了
    45         for (Object s :res){
    46             System.out.println(s);  //tom alex
    47         }
    48 //        for (int i =0;i<res.length;i++){
    49 //            System.out.println(res[i]);
    50 //        }
    51 
    52 
    53 
    54         /*
    55          * boolean remove(Object o) 方法
    56          *  删除指定的元素
    57          * 删除失败的时候,返回false
    58          * 而且,只会删除第一个。不会删除ArrayList 中的每一个
    59          * */
    60         System.out.println(collection);
    61         collection.remove("tom");
    62         System.out.println(collection);
    63 
    64     }
    65 
    66 }
    Collection 接口中的基本方法_add_clear_remove_contains_toArray

    Iterator 接口 (Iterator 迭代器) 的学习:

    之所以有迭代器,就是为了应对 对于不同的容器,取出的方式保持不变!!!

    Iterator 是个接口,它对collection 进行迭代的迭代器!

    Iterator 接口 中的抽象方法:

    我们用它的实现类对象 来学习它的抽象方法。

    我们可以知道,Collection 接口中定义了一个方法 Iterator iterator();  

    所以,我们可以通过使用Collection 的实现类 ArrayList, 然后它重写Collection 的iterator() 方法,该方法就返回了一个 Iterator 接口的对象。就可以用它了!

     1 package cn.zcb.demo01;
     2 
     3 
     4 import java.util.ArrayList;
     5 import java.util.Iterator;
     6 
     7 public class Test {
     8     public static void main(String[] args) {
     9         ArrayList <String> arrayList = new ArrayList<>();
    10         arrayList.add("ad");
    11         arrayList.add("tom");
    12         arrayList.add("egon");
    13         arrayList.add("alex");
    14 
    15         //得到 Iterator 接口的 可用对象。  Collection 中的 Iterator iterator() 方法会返回!
    16         //得到迭代器
    17         Iterator iterator =  arrayList.iterator();  //发生多态!方法的返回值是 Iterator 实现类的对象,具体是实现类是什么不重要!
    18         while (iterator.hasNext()){
    19             System.out.println(iterator.next());
    20         }
    21     }
    22 
    23 }
    迭代器的基本使用 

    迭代器的执行过程:

    迭代器是遍历所有集合的通用模式!

    而且迭代器只能使用一次,迭代完之后,就不能再次使用了!!!

    除了使用while() 以外,也可以使用for 循环 来迭代!

     1 package cn.zcb.demo01;
     2 
     3 
     4 import java.util.ArrayList;
     5 import java.util.Iterator;
     6 
     7 public class Test {
     8     public static void main(String[] args) {
     9         ArrayList <String> arrayList = new ArrayList<>();
    10         arrayList.add("ad");
    11         arrayList.add("tom");
    12         arrayList.add("egon");
    13         arrayList.add("alex");
    14 
    15         Iterator iterator =  arrayList.iterator();  
    16             while (iterator.hasNext()){
    17             System.out.println(iterator.next());
    18         }
    19         
    20         //使用for 循环进行遍历, 注意:它比while 节约内存,因为 它的迭代器是个局部变量,而while的迭代器是个main中的变量。
    21         for (Iterator iterator1 = arrayList.iterator();iterator1.hasNext();){
    22             System.out.println(iterator1.next());
    23         }
    24     }
    25 }
    View Code

    while的形式比for 的简洁。  for 比while 节约内存 ,for 循环执行完之后,就立即释放了内存,而while 要当main执行完毕之后!

    集合迭代器 中的转型:

     1 package cn.zcb.demo01;
     2 
     3 import java.util.ArrayList;
     4 import java.util.Collection;
     5 import java.util.Iterator;
     6 
     7 public class Test {
     8     public static void main(String[] args) {
     9         /*
    10         * 集合Collection 可以存储任意的对象。
    11         * */
    12 
    13 //        Collection <String> collection = new ArrayList<>();  //我们通常使用的形式 。。
    14         //但是,也可以使用下面的形式
    15         Collection collection = new ArrayList();  //这时的 对象里可以有任意类型!
    16         collection.add("tom");  //String  但是,放进去都被提升为了 Object类型 向上转型!
    17         collection.add(1);  //Integer
    18         collection.add('1');  //Character
    19 
    20 
    21         Iterator iterator = collection.iterator();
    22         while (iterator.hasNext()){
    23 //            System.out.println(iterator.next());  //iterator.next() 的返回值的类型也是 Object 类型。
    24             Object obj = iterator.next();
    25             System.out.println(obj);
    26         }
    27         //上述 虽然可以,但是如果此时想调用 子类的特有方法的时候就必须 要进行强转。强制向下强制。例如。想使用String() 的.length 属性
    28         //所以,总结,在使用集合Collection 的时候,最好还是加上类型,这样可以避免 转型,以及后面 要使用子类的特有方法时候的向下强转。
    29 
    30     }
    31 }
    View Code

    总结,在使用集合Collection 的时候,最好还是加上类型!

    增强的for 循环:

    原来的接口 Collection 就不是根接口了,而是变成了Iterable .

    这个Iterable 的出现就是 实现 增强的for循环。  

    案例:

    集合中存储 我们自定义的Person 类型,然后用增强for 去遍历它!

     1 package cn.zcb.demo02;
     2 
     3 public class Person {
     4     public String name;
     5     public int age;
     6 
     7     public Person(){}
     8     public Person(String name,int age){
     9         this.name = name;
    10         this.age = age;
    11     }
    12 }
    Person.java
     1 package cn.zcb.demo01; //当前的包 
     2 import cn.zcb.demo02.Person; 
     3 import java.util.ArrayList;
     4 
     5 public class Test {
     6     public static void main(String[] args) {
     7         ArrayList <Person> arrayList =  new ArrayList<>();
     8         arrayList.add(new Person("tom",18));
     9         arrayList.add(new Person("alex",10));
    10         arrayList.add(new Person("egon",20));
    11         arrayList.add(new Person("tim",9));
    12 
    13         for (Person person : arrayList){
    14             System.out.println("Name: "+person.name + " Age: "+person.age);
    15         }
    16     }
    17 }
    Test.java

    增强for 循环是不能操作索引的,它的出现的主要目的是用来进行遍历! 

    泛型:

    使用泛型(加入 尖括号),使得程序变得更加安全。因为如果没有使用泛型 的话,那么如果使用子类特有方法时候必须要强制,如果一个集合中有不同的类型,当迭代的时候就可能报错!

    Java 中的伪泛型:

    Java中的泛型只是在 编译之前体现的,一旦编译成功之后得到的class 文件是不能体现出泛型的!

    如果不符合的数据,它在编译的时候就不会通过了,所以说 ,它是通过 编译的收到来保证安全的。

    据说,C++ 就是真泛型。

    泛型的定义与使用:

    带有泛型的类:

    E 接收的就是一个一种类型!

    Interator<E>  也是一个带有泛型的类!

    泛型就是使得  类中的方法的参数的类型 更加灵活。   

    带有泛型的接口:

    使用接口的时候有两种使用方法:
    1,先实现接口,不理会泛型。

    这样,在使用实现类的时候一起指定具体的数据类型。   

    2,在实现接口,也指定了数据类型 

    这时候的数据类型就已经定了,就是固定的了,不灵活,

    所以一般都是使用第一个。

    使用泛型的好处:

    最大的好处就是安全问题,主要是在强转的时候出现的。

    例如,如果不用泛型指定具体的数据类型,此时可能会出现异常,如下程序:

     1         //遍历
     2         for (Object item :arrayList1){
     3             //强制转为 String  
     4             String s = (String)item;  
     5             System.out.println(s.length());
     6             //此时的问题是 因为没有使用泛型指定具体的数据类型,所以
     7                 //ArrayList 中可以存任意的数据类型,
     8                 //但是,此时第四个不是String ,它不能强转为String .  
     9                 //于是,编译失败
    10         }
    View Code

    将运行时期的报错提前到了编译时候。  

    泛型的通配符:

     1 package cn.zcb.demo01; //当前的包
     2 
     3 import com.sun.jdi.ArrayReference;
     4 
     5 import java.util.ArrayList;
     6 import java.util.Collection;
     7 import java.util.HashSet;
     8 import java.util.Iterator;
     9 
    10 public class Test {
    11     public static void main(String[] args) {
    12 
    13         ArrayList<String> arrayList = new ArrayList<>();
    14         arrayList.add("tom");
    15         arrayList.add("egon");
    16         arrayList.add("ALEX");
    17 
    18         HashSet<Integer> hashSet = new HashSet<>();
    19         hashSet.add(10);
    20         hashSet.add(54);
    21         hashSet.add(5);
    22 
    23         myIterator(arrayList);
    24         myIterator(hashSet);
    25 
    26     }
    27     /*
    28     * 现在的需求是 :定义个方法 既能遍历ArrayList 也可以遍历HashSet
    29     * //它的参数 既不能是 ArrayList 也不能是 HashSet
    30     * 只能是它们共同的接口 Collection  但是,Collection 的泛型用什么类型呢?
    31     *
    32     * 这又是个问题。
    33     * 这里用泛型的通配符 , 这里用的不是*  而是 ?  !
    34     *
    35     * */
    36     public static void myIterator(Collection<?> collection){
    37         Iterator<?> it =  collection.iterator();
    38         while (it.hasNext()){
    39             System.out.println(it.next());
    40             
    41             //这时的it 已经不确定是什么类型了,所以此时是不能强转的。
    42             //所以总结:通配符?  的时候,只是用于遍历!!!
    43         }
    44     }
    45 
    46 
    47 
    48 }
    View Code

    通配符一般只用来做遍历用。

    泛型的限定:

    为了解决上述通配符 不能进行强制转换,只能用来遍历的缺点,于是有了泛型的限定。

    三个类 它们的父类都是 Employee.  

    此时我们想 写一个方法,然后调用三个子类的work()  方法。

    如果方法的参数直接写为 ArrayList<?> arrayList ,

    这时的?代表的是Object 类,如果调用work() 方法,必要要强制转为它们共有的父类Employee(方法走子类重写!!!),但是这是有风险的。 因为如果假设有一个新的类 ArrayList<String> arr,它里面的元素是不能强制转为Employee 的。  

    这时可以使用泛型的限定。

     ?代表子类不确定,但是它们的父类都是一定的。都是Employee。  

    限定有上限,也可以有下限。 

    关于多态的补充: 

    运行时候:成员变量是调父类, 成员方法是调子类。   (重点)

    编译的时候:全部调用父类,父类没有报错。  

  • 相关阅读:
    ural1238. Folding(记忆化)
    URAL1410. Crack
    树套树Day1线段树套平衡树bzoj3196
    noipd2t3列队
    NOIP2017D1T3
    uoj279温暖会指引我们前行
    一篇打脸文
    Link-Cut Tree
    重口味费用流
    bzoj1000~1025
  • 原文地址:https://www.cnblogs.com/zach0812/p/11809529.html
Copyright © 2020-2023  润新知