[java]day07Collection&泛型

集合

集合长度可变, 数组长度不可变
集合能存引用类型, 数组可存任意类型.

集合都需要用get/set/remove等包装方法来操作元素.

集合继承关系

Collection是单列集合根接口

java.util.
    java.util.Collection
        list: 有序/有id/可重复
            ArrayList
            LinkList

        set: (无序)/无id/不可重复
            hashset:无序,底层哈希表
                linkhashset: 有序
    map


ArrayList(底层是可变长数组)和LinkedList(底层是链表)操作方法基本一致,不过多了一些头尾元素的操作方法. 

查询多的场景用ArrayList.
增删多的是用LinkedList

Collection接口公共功能

基本都是无参方法. 因为list支持index, 而set无index.

add
isEmty
size
remove
clear
contains
toArray

iterator()

集合接口继承层次较深, 要研究上层定义的公共方法, 使用多态方式创建.
Collection coll = new ArrayList<>();

public class Test {
    public static void main(String[] args) throws Exception {
        Collection<String> coll = new ArrayList<>();
        coll.add("m1");
        coll.add("m2");
        coll.add("m3");
        coll.add("m1");

        System.out.println(coll.isEmpty());
        System.out.println(coll.size());
        System.out.println(coll.remove("m1"));
        System.out.println(coll);
        System.out.println(coll.contains("m1"));

        coll.add("g1");
        coll.add("g2");

        //集合遍历(集合没有索引),转为数组后遍历
        Object[] arr = coll.toArray();
        for (int i = 0; i < arr.length; i++) {
            Object obj = arr[i];
            //System.out.println(arr[i]);
            //获取数组元素的某些属性不方便
            System.out.println(obj + "  " + ((String) obj).length());
        }
        coll.clear();
        System.out.println(coll);
    }
}

iterator

集合的遍历方式: 1.传统的for 2.iterator(迭代器) 3.增强for

如ArrayList实例生成一个迭代器对象list.iterator(),对这个对象迭代. 先判断有无元素, 然后取出元素,直到取完为止.称为迭代.

iterator接口常用方法

java.util.iterator:
    public abstract boolean hasNext()
    public abstract E next()
    public abstract void remove()
public class Test {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("m1");
        list.add("m2");
        list.add("m3");
        
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        
        Iterator<String> it = list.iterator();
        while (it.hasNext()){
            System.out.println(it.next());
        }

        for (String s : list) {
            System.out.println(s);
        }
    }
}

iterator实现原理

iterator内部类实现.iterator()方法返回一个实现来Iterator接口的实例.

public class ArrayList<E> extends AbstractList<E>{
    public Iterator<E> iterator() {
        return new Itr();
    }
    private class Itr implements Iterator<E> {
        ...
        public boolean hasNext()
        public E next()
        ...

增强for

增强for主要用于遍历功能, 不是用来增删改的
用增强for遍历,期间不要增删改元素, 会抛错(ConcurrentModificationException). 因为它线程不安全(但高效)

public class Test {
    public static void main(String[] args) {
        int[] arr = {11, 22, 33};
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }

        for (Integer i : arr) {
            System.out.println(i);
        }
    }
}
public class Test {
    public static void main(String[] args) {
        Collection<String> coll = new ArrayList<>();
        coll.add("m1");
        coll.add("m2");
        coll.add("m3");

        Iterator<String> it = coll.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }
        
        for (String s : coll) {
            System.out.println(s);
        }
    }
}
  1. 在进行集合元素获取时,如果集合中已经没有元素了,还继续使用迭代器的next方法,将会抛出 java.util.NoSuchElementException没有集合元素异常。
  2. 在进行集合元素获取时,如果添加或移除集合中的元素 , 将无法继续迭代 , 将会抛出 ConcurrentModificationException并发修改异常.

泛型(generic)

可以在类或方法中预支地使用未知的类型。
广泛的类型, 代码模版化思路

public class ArrayList<E>

public class ArrayList<Integer>
public class ArrayList<String>

//有这些标记
E - Element (在集合中使用,因为集合中存放的是元素)
T - Type(Java 类)
K - Key(键)
V - Value(值)
N - Number(数值类型)
? - 表示不确定的java类型
S、U、V  - 2nd、3rd、4th types
泛型 确定时机 定义 实例化
定义在类上, 修饰字段类型 实例化类时确定类型 class MyClass<T> MyClass<Integer> mc = new MyClass<>();
定义在方法上,修饰方法参数类型 调用方法时确定类型 public <T> void show(T s) mc.show(10);
定义在接口上,约束实现类方法的参数类型 实现接口时确定类型 interface MyInter<T> class MyInterImplA implements MyInter<String>

如果不指定类型,直接使用,默认Object类型
MyClass mc = new MyClass();

使用泛型好处

1.避免强转
2.错误提前到编译时
3.类型统一,add/get
4.实现代码模版化,将数据类型当错参数传递

注意: ArrayList arr2 = new ArrayList(); //public class ArrayList 带泛型的类, 如果直接new,得到的类型是Object.

public class Test {
    public static void main(String[] args) {
        ArrayList<String> arr = new ArrayList<>();
        arr.add("m1");
        arr.add("m2");
        arr.add("m3");
        for (String s : arr) {
            System.out.println(s + " " + s.length());
        }
        ArrayList arr2 = new ArrayList();  //public class ArrayList<E> 带泛型的类, 如果直接new,得到的类型是Object.  
        arr2.add("m1");
        arr2.add("m2");
        arr2.add("m3");
        //arr2.add(1000);//编译没错,运行时(String) s)转换元素类型, 会导致ClassCastException
        for (Object s : arr2) {
            System.out.println(s + " " + ((String) s).length());//强制类型转换
        }
    }
}

泛型的定义与使用

E element
T type
K V

定义在类上

定义在类上
    用于约束实例属性的类型
    创建class时确定类型


public class Test {
    public static void main(String[] args) {
        MyClass<String> mc = new MyClass<>();
        mc.setT("m1");
        //mc.setT(1000); //只能传str
        System.out.println(mc.getT());

        MyClass<Integer> mc2 = new MyClass<>(1000);
        int t = mc2.getT();
        System.out.println(t);
    }
}


class MyClass<T>{
    private T t;

    public MyClass() {
    }

    public MyClass(T t) {
        this.t = t;
    }

    public T getT() {
        return t;
    }

    public void setT(T t) {
        this.t = t;
    }
}

定义在方法上

定义在方法上
    用于约束方法参数的类型
    调用方法时确定类型

public class Test {
    public static void main(String[] args) {
        MyClass<String> mc = new MyClass<>();
        mc.print("m1"); //只能str
        //mc.print(22);

        mc.show(100);//任意类型
    }


}

class MyClass<T> {
    public void print(T t) {
        System.out.println(t);
    }

    public <E> void show(E e) {//方法上定义属于自己的泛型
        System.out.println(e);
    }
}

定义在接口上

定义在接口上
    约束(类实现)接口方法的参数类型
    类实现接口是确定类型

public class Test {
    public static void main(String[] args) {
        MyInterImplA mia = new MyInterImplA();
        mia.print("hi");

        MyInterImplB<String> mib = new MyInterImplB<>();
        mib.print("hi");
        MyInterImplB<Integer> mib2 = new MyInterImplB<>();
        mib2.print(1212);

    }
}

interface MyInter<T> {
    void print(T t);
}

//定义实现类时,确定接口上泛型的具体类型
class MyInterImplA implements MyInter<String> {

    @Override
    public void print(String s) {
        System.out.println(s);
    }
}

//定义实现类时,不确定接口的类型,那么
// 实现类必须定义为泛型类
// 实现类上泛型变量名要和接口上泛型变量名一致
class MyInterImplB<T> implements MyInter<T> {

    @Override
    public void print(T t) {
        System.out.println(t);
    }
}
public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>

public interface List<E> extends Collection<E> 
public interface Collection<E> extends Iterable<E>
public interface Iterable<T>

泛型通配符

只能用来匹配泛型,不能用来定义泛型.

通配符基本使用

public class Test {
    public static void main(String[] args) {
        ArrayList<String> s = new ArrayList<>();
        s.add("m1");

        ArrayList<Integer> in = new ArrayList<>();
        in.add(100);
        printArrayList(s);
        printArrayList(in);
    }

    //public static void printArrayList(ArrayList<Integer> list){
    //
    //}
    //代表任意一种引用类型,只能用来匹配泛型,不能用来定义
    public static void printArrayList(ArrayList<?> list){
        for (Object o : list) {
            System.out.println(o);
        }
    }
}

public class Test {
    public static void main(String[] args) {
        //泛型不存在多态,创建对象时候,左右两边<>保持一致
        ArrayList<Object> list1 = new ArrayList<Object>();
        //ArrayList<Object> list2 = new ArrayList<String>();

        //ArrayList<?> 可以接受ArrayList任意类型的泛型对象(<>随便写一种引用类型都ok)
        ArrayList<?> list;
        list = new ArrayList<>();
        list = new ArrayList<Integer>();
        list = new ArrayList<String>();
        list = new ArrayList<Student>();
    }
}

通配符高级使用

/*
 * 父类: Person
 * 子类: Woker
 * 子类: Teacher
 * 子类: JavaTeacher
 *
 * 一个类的子类可以有任意多个,如何表示一个类的任意子类呢
 *
 * ? extends Person: 表示是Person类型或者Person类型的任意子类
  * ? extends E  // E类型的上限

 * ? super Teacher: 表示是Teacher类型或者Teacher类型的任意父类
 * ? super E  // E类型的下限
 * */

public class Test {
    public static void main(String[] args) {
        ArrayList<Person> list1 = new ArrayList<>();
        ArrayList<Woker> list2 = new ArrayList<>();
        ArrayList<Teacher> list3 = new ArrayList<>();
        ArrayList<JavaTeacher> list4 = new ArrayList<>();
        ArrayList<Integer> in = new ArrayList<>();
        printArrayList(list1);
        printArrayList(list2);
        printArrayList(list3);
        printArrayList(list4);
        //printArrayList(in);
        
        
    }
    //只能打印Person子类对象
    public static void printArrayList(ArrayList<? extends Person> list) {
        for (Object o : list) {
            System.out.println(o);
        }
    }
}

class Person {
}

class Woker extends Person {
}

class Teacher extends Woker {
}

class JavaTeacher extends Teacher {
}
posted @ 2020-02-27 20:49  mmaotai  阅读(1)  评论(0编辑  收藏  举报