day17_Collection

  • Collection集合
  • 迭代器
  • 增强型for循环
  • 泛型

目标:

  • ​ 区分集合和数组的区别
  • ​ 使用Collection集合的常用功能
  • ​ 使用迭代器
  • ​ 掌握集合使用细节
  • ​ 使用集合存储自定义类型
  • ​ 使用for each循环遍历集合
  • ​ 使用泛型定义集合对象
  • ​ 理解泛型上下限
  • ​ 阐述泛型通配符作用

Collection集合

​ 概述: 前面我们已经接触过ArrayList集合,那么集合到底是什么呢?

​ 集合是Java中提供的一种容器,可以来存储多个数据。集合和数组既然都是容器,他们有何区别?

  • ​ 数组的长度是固定的,集合的长度是可变的
  • ​ 数组中存储的是同一种数据类型的元素,可以存储基本数据类型,也可以存储引用数据类型。集合存储的都是引用数据类型,对象的数据类型可以不一致。在开发当中一般当对象多的时候,使用集合存储数据。

集合的框架

​ JavaSE提供了满足各自需求的API,我们在使用API的时候,先了解其继承与接口操作的框架,然后才能理解使用哪个类更灵活的适合设计你的程序。

​ 根据集合的存储结构,分为了两个大类:

  • ​ 单列集合 ---java.util.Collection
  • ​ 双列集合 ---java.util.Map
Vector
List接口(有序) ArrayList
LinkedList
Collection接口
TreeSet(无序)
Set接口 HashSet(无序) LinkedHashSet(有序)

List接口:

  1. ​ 有序的集合(存储和取出元素顺序相同)
  2. ​ 允许存储重复元素
  3. ​ 有索引,可以进行普通for遍历

Set接口:

  1. ​ 不允许存储重复性元素
  2. ​ 没有索引(不能使用普通for遍历)

Collection接口:

  1. ​ 定义的是所有单列集合中共性的API方法,所有单列集合都可以使用共性的方法

  2. ​ 没有带索引的方法

    它是单列集合的根接口,用于存储一系列符合某种规则的元素,又两个重要的子接口java.util.Listjava.util.Set

Collection集合常用功能

  • ​ public boolean add(E e):把给定的对象添加到当前的集合当中
  • ​ public void clear():清空集合当中所有元素
  • ​ public boolean remove(E e):把给定的对象从当前集合中删除掉
  • ​ public boolean contains(E e):判断当前集合当中是否包含给定的对象
  • ​ public boolean isEmpty():判断当前集合是否为空
  • ​ public int size():获取当前集合元素的个数
  • ​ public Object[ ] toArray():把当前集合中的元素,存储到一个数组中

迭代器Iterator接口

​ 在程序开发过程中,经常需要遍历集合中所有元素,针对此情况,JDK官方提供了一个java.util.Iterator,这个接口也是集合当中的一员,但是它与Map、Collection接口不同。Map、Collection集合主要是来存储元素的,而Iterator主要用于迭代访问Collection与Map集合中的元素。因此,经常把Iterator对象称为迭代器

​ 遍历Collection集合当中的元素,首先应获取该集合的迭代器,通过迭代器完成迭代

  • ​ public Iterator iterator():获取集合对应的迭代器

    迭代的具体实现:在每次取元素之前首先判断有没有元素,如果有,就把这个元素取出,继续再判断,如果还有就再取一次出来。直至集合为空。

Iterator接口的常用方法:

  • ​ public E next():获取迭代的下一个元素
  • ​ public boolean hasNext():如果集合当中仍有元素可以迭代,则返回true,如果没有元素则返回false

​ 在调用Iterator接口当中的next方法之前,迭代器的索引位于第一个元素之前,不指向任何元素,当第一次调用迭代器的next方法后,迭代器的索引向后移动一位,指向第一个元素并将该元素返回。当再次调用next方法时,迭代器的索引会指向第二个元素并将该元素返回。依次类推,直至hasNext方法返回false。表示迭代器达到集合的末尾,终止对元素遍历,如果再取,则抛出java.util.NoSuchElementException

备注:Iterator 接口也是有泛型的,迭代器的泛型是跟着集合走的(集合当中定义的什么类型,迭代器就是什么类型)

增强for循环

​ 在JDK1.5之后出现了一个新的循环结构,for each循环,(增强型for循环)。专门遍历数组和集合 它的内部原理其实是由迭代器实现,在迭代过程中,不能对集合当中的元素进行增删操作。

格式:

for(元素的数据类型 变量名 :Collection集合或者数组){
    //操作代码
    //...
}

主要用于遍历Collection集合或者数组,在遍历的过程中,一定不要进行增删操作。

示例:
   for (int i:arr) {//遍历数组
            System.out.println(i);
   }
   for (String e: coll) {//遍历集合
            System.out.println(e);//e表示集合中的元素
   }

备注:目标只能是Collection集合或者数组,增强for循环仅仅是作为遍历操作出现。简化迭代器的操作

泛型

​ 是一种未知的数据类型,当我们不知道要使用什么样的数据类型的时候,可以使用泛型。我们也可以将泛型看做是一个变量,用来接收数据类型(预支的使用未知的数据类型)

  • ​ E e :Element 元素
  • ​ T t :Type 类型
定义集合的时候   不知道要使用什么样的数据类型的时候,使用泛型
public class ArrayList<E>{
		public boolean add(E e){}
		public E get(int index){}
}
创建集合对象的时候,一定要确定具体泛型类型 当没有指定具体数据类型时,默认指定为Object类型
ArrayList<String> list =new ArrayList();
public class ArrayList<String>{
    	public boolean add(String){}
		public String get(int index){}
}

使用泛型的好处:

  • ​ 避免类型转换之间的麻烦,存储的是什么数据类型,取出的就是什么样的数据类型
  • ​ 运行期异常提前到了编译期

备注:泛型其实也是数据类型的一部分,一般我们将类名和泛型合并一起看做数据类型

泛型的定义与使用

​ 泛型可以灵活的将数据类型应用到不同的类、方法、接口当中。将数据类型作为参数进行传递

因为我们的集合框架体系中,大量的使用了泛型。

定义和含有泛型的类
修饰符  class  类名<代表泛型的变量>{
}
例如:
public class GenericDemo02<W> {
    private W name;
    public GenericDemo02() {
    }
    public GenericDemo02(W name) {
        this.name = name;
    }
    public W getName() {
        return name;
    }
    public void setName(W name) {
        this.name = name;
    }
}//定义的时候使用未知泛型变量,使用的时候确定具体类型(创建对象的时候)
定义和含有泛型的方法
修饰符 <代表泛型的变量> 返回值类型  方法名(泛型参数列表){
}
例如:
public class GenericMethod{
	//定义带有泛型的方法
    public <VIP> void show(VIP vip){
        System.out.println(vip);
    }
    //定义一个含有泛型返回值的方法
     public <VIP> VIP show(VIP vip){
        //...
         return vip;
    }
}
main(){
    new GenericMethod().show("abc");// 自动转换为String类型 vip = "abc"
    new GenericMethod().show(123);// 自动转换为int类型  vip = 3.14
}
定义和含有泛型的接口
修饰符 interface 接口名<代表泛型的变量>{
}
例如:
public interface Collection<E>{
	public void add(E e);
    public Iterator<E> iterator();
} 
//自定义的泛型接口
public interface MyGenericInterface<T>{
    void add(T t);
    T get();
}
泛型接口使用格式:

​ 1.定义实现类时,可以确定泛型的类型

public class MyInterfaceImpl implements MyGenericInterface<String>{
    @Override
    void add(String str){};
    @Override
    String get(){};
}//此时泛型T的值就是String类型

​ 2.始终不确定泛型的类型,直到创建对象的时候才确定泛型类型

public class MyInterfaceImpl02<T> implements MyGenericInterface<T>{
    @Override
    void add(T t){};
    @Override
    T get(){};
}//创建对象的时候必须确定泛型类型
原文地址:https://www.cnblogs.com/mitoris/p/14070499.html