07 集合Collection、增强for、泛型基础使用

07 集合Collection、增强for、泛型基础使用

1、集合的继承体系

在这里插入图片描述

2、Collection

Collection是一个接口,如果要用,需要使用实现类,最常用的实现类是ArrayList

  • Collection中的常见方法:
    public boolean add(E e):把给定的对象添加到当前集合中。
    public boolean remove(E e):把给定的对象在当前集合中删除
    public void clear():清空集合中的所有元素
    public boolean contains(Object obj):判断当前集合中是否包含给定的对象
    public boolean isEmpty();判断当前集合是否为空。
    public int size():返回集合中元素的个数。
    public Object[] toArray();把集合中的元素储存到数组中去。
public class Demo01CollectionTest {
    public static void main(String[] args) {
        Collection<String> co = new ArrayList<>();
        co.add("牛顿");
        co.add("爱因斯坦");
        co.add("霍金");
        System.out.println("co:" + co);
        /*co.clear();
        System.out.println("co:" + co);*/
        co.remove("霍金");
        System.out.println("co:" + co);
        boolean flag = co.contains("牛顿");
        System.out.println("co:" + co);
        System.out.println(flag);
        System.out.println(co.isEmpty());
        System.out.println(co.size());

        //将集合转换成数组
        Object[] obj = co.toArray();
        for (Object o : obj) {
            System.out.println(o);
        }
    }
}

3、Iterator 迭代器

	我们之前都是使用for循环结合索引的方式遍历集合,这种遍历方式不能适用于所有的集合,因为不是所有的集合都有索引。
 	有一种通用的遍历集合的方式,叫做迭代器遍历。
	迭代器就是遍历集合的一个工具,内部有一个光标,这个光标最开始指向集合的最开头。

在Collection中有一个方法可以获取迭代器,这个方法叫做iterator
Iterator iterator();获取集合的迭代器对象。
Iterator表示迭代器,如果要使用迭代器遍历,还需要用到Iterator中的一些方法。

boolean hasNext(): 判断是否还有元素可以获取。
E next(): 获取当前光标位置的元素,将光标向后移动。

迭代器遍历的步骤:
1、调用集合的iterator方法获取迭代器对象
2、调用迭代器的hasNext判断是否有元素可以获取。
3、如果有元素可以获取,那么就调用迭代器的next()方法,获取元素,并把光标向后移动。
有一种通用的遍历集合的方式,叫做迭代器遍历。
迭代器就是遍历集合的一种工具,内部有一个光标,这个光标最开始指向集合的最开头。

  • 在Collection中,有一个方法可以获取迭代器,这个方法叫做iterator。
  • boolean hasNext():
  • E next();

当我们在迭代器的遍历过程中,通过集合的方法对集合的长度进行改变(调用集合的增删),就会引发修改异常(ConcurrentModificationException),要避免在迭代器遍历的过程中对集合进行增删操作。

Collection<Student> list = new ArrayList<>();
//Iterator<Student> iterator1 = list.iterator();放在该位置list长度发生变化。引发修改异常。
list.add(new Student("lizi2", 23));
list.add(new Student("lizi3", 22));
list.add(new Student("lizi1", 21));
Iterator<Student> iterator1 = list.iterator();
/*for (Student student: list){
    System.out.println(student);
}*/
while (iterator1.hasNext()) {
    System.out.println(iterator1.next());
}

4、增强for循环

在jdk5的时候,多了一个新特性叫做增强for循环(foreach),可以遍历集合或者数组
增强for的格式:
for(数据类型 变量名:容器名 ){
Sout(变量名);
}
格式解释:数据类型:要遍历的容器中存放的是什么类型的数据,那么这个数据类型就写什么。 变量名:该变量表示容器中的每一个元素。
容器名:可以是集合或者数组。
使用增强for遍历数组
增强for其实是一个语法糖,语法糖其实是本质没有变,只不过是写法更加简洁了。

  • 增强for遍历数组,本质使用的还是普通for循环。
  • 增强for的优缺点:省去了对索引的操作,语法简洁。
    但是也由于不能操作索引,如果要在遍历的时候操作索引,还需要使用普通for循环。
    增强for遍历集合的本质:增强for遍历集合的本质是迭代器。
public class Demo02Generic {
    public static void main(String[] args) {
        //创建集合
        ArrayList<String> list = new ArrayList<>();
        //添加元素
        list.add("hello");
        list.add("world");
        list.add("java");
        //增强for遍历
        for (String str : list) {
            System.out.println(str);
        }
    }
}

5、泛型

泛型是一种未知的,不确定的数据类型。
比如ArrayList,其中尖括号中的E就是一种未知的不确定的数据类型,他就是一个泛型。
泛型类型不是一直未知的,,当我们使用这个类的时候(比如创建对象),那么这个泛型的类型会被确定下来。
比如创建对象集合 ArrayList list = new ArrayList<>()此时泛型就是Student类型
(1)泛型可以省略,如果泛型省略,想当于泛型是Object
(2)泛型的好处:省略了向下转型的操作
将运行时期的问题提前到了编译时期;
(3)泛型擦除:java中的泛型都是伪泛型,泛型只在源代码阶段有效,一旦编译,泛型就会消失,俗称,泛型擦除。

public class Demo01Generic {
    public static void main(String[] args) {
        //创建集合,省略泛型
        ArrayList list = new ArrayList();
        //添加元素
        //list.add(100); 运行时期报错
        list.add("hello");
        list.add("world");
        list.add("java");

        //遍历集合,拿到集合中的每一个字符串并输出该字符串的长度
        for (Object obj : list) {
            //向下转型
            String s = (String) obj;
            //调用方法获取长度
            System.out.println(s.length());
        }
        System.out.println("===========================");
        //创建集合,使用泛型
        ArrayList<String> list2 = new ArrayList<>();
        //list2.add(100); 编译时期报错。
        list2.add("hello");
        list2.add("world");
        list2.add("java");
        //遍历集合,拿到集合中的每一个字符串并输出该字符串的长度
        for (String s : list2) {
            System.out.println(s.length());
        }

    }
}

泛型的各种使用条件

(1)泛型类

泛型类泛型是一种未知的不确定的数据类型:如果在类名后面写上,那么就表示在这个类上定义了一个未知的,不确定的数据类型T,在整个类中都可以使用这个数据类型T带有泛型的类也叫作泛型类。这个T也可以是其他字母。
泛型类型并不是一直未知的一直不确定的,当我们使用这个类的时候,泛型所表示的数据类型就会被确认下来。

(2)泛型方法

泛型方法如果想要延后泛型类型的确认时间,那么我们可以将泛型定义在方法上面。如果将泛型定义在方法上,那么这个方法就是泛型方法。
定义在方法上的泛型需要在调用方法的时候才能确定类型,才能指定这个泛型的类型,在方法上定义的泛型,只能在自己的方法中使用。

泛型方法的定义格式:
修饰符 <泛型类型> 返回值类型 方法名(参数列表){
//方法体

}
public <E> E getSame(E e){
    return e;
}

//定义方法,接收什么类型的参数,就得到什么类型的结果
//第一个表示定义了泛型类型E(不确定的类型)
//后面的两个E表示使用了泛型E当做了参数类型和返回值类型
//在方法上定义的泛型,需要等到调用方法的时候才能够指定他的类型

小结:泛型类和泛型方法:
如果在类上面定义泛型,那么这个类为泛型类,在类上面定义泛型,需要使用这个类的时候,才能确定这个类表示的是什么类型的。
如果在方法上面定义泛型,这个方法就是泛型方法,需要在调用方法的时候才能知道这个泛型是什么类型的。

(3)泛型接口

如果在接口名后面加上尖括号,那么这个接口也就变成了泛型接口。
在接口上定义的泛型在整个接口中可以使用。

public interface MyInterface<T> {
    T method(T t);
}

泛型接口的使用:
1.实现类在实现接口的时候直接指定泛型的类型。( 要求:MyClassA实现MyInterface接口的时候直接指定MyInterface中的泛型。在实现接口的时候,可以在接口名后面加上尖括号来指定接口中的泛型类型)

public class MyClass implements MyInterface<Pad> {
    @Override
    public Pad method(Pad pad) {
        return pad;
    }
}

2.实现类在实现接口的时候不指定泛型, 在使用实现类(创建实现类对象)的时候再指定泛型。(实现类在实现接口的时候不指定泛型。我们在定义类或接口的时候,仅仅在当前类或接口的名字后面写的尖括号才是在定义泛型。)

public class MyClassB<T> implements MyInterface<T> {
    @Override
    public T method(T t) {
        return t;
    }
}

泛型通配符

泛型之间是没有继承关系的,ArrayList不是ArrayList的父类
如果想要让方法的参数可以接收任何类型的泛型,那么可以使用泛型通配符?

?表示泛型通配符,可以匹配任何类型的泛型。
注意:泛型通配符要用在参数位置被动匹配,不能主动使用。

如果要对?泛型通配符的范围进行限制,那么可以使用泛型限定。

<? extends A>:表示泛型只能是A类,或者A类的子类。上限。
<? super A>: 表示泛型只能是A类,或者A类的父类。 下限。

泛型主要用于代码重构。

public class Demo01Generic {
    public static void main(String[] args) {
        //创建ArrayList,保存字符串
        ArrayList<String> strList = new ArrayList<>();
        //添加元素
        strList.add("hello");
        strList.add("world");
        strList.add("java");
        //调用printArrayList方法,遍历
        printArrayList(strList);

        //创建ArrayList,保存Integer
        ArrayList<Integer> intList = new ArrayList<>();
        //调用printArrayList方法,遍历
        printArrayList(intList);

        //创建集合,泛型使用通配符?
        //ArrayList<?> list = new ArrayList<>();
        //list.add();
    }

    /*
        定义方法,这个方法用来遍历集合(存放任何类型的数据的集合)
     */
    public static void printArrayList(ArrayList<?> list) {//?泛型通配符可以匹配任何类型的泛型。
        //对集合进行遍历
        for (Object obj : list) {
            System.out.println(obj);
        }
    }
}

附加:调用Collections工具类中的静态方法shuffle
Collections.shuffle(集合):随机排序生成方法。

猜你喜欢

转载自blog.csdn.net/weixin_45507013/article/details/99177096