java中Collection、泛型

1.1 集合概述

1.什么是集合:

  • 一个用来存储多个元素的容器。

2.数组和集合的区别:

  • 数组:长度固定,可以存储基本数据类型  ,也可以存储引用数据类型。
  • 集合:长度可变,只能存储引用数据类型,如果存储基本数据类型则需要使用对应的包装类。

3.集合的分类:

  • 单列集合(Collection):每次存储元素时只存储一个元素。
  • 双列集合(Map):每次存储元素时要 存储两个元素。

1.2 Collection集合体系 

  • Collection:父接口  所有单列集合的父类
  • List:子接口
  1. ArrayList:实现类
  2. LinkedList:实现类
  3. Vector:实现类
  • Set:子接口
  1. HashSet:实现类
  2. LinkedHashSet:实现类

  •  其中,橙色框里写的都是接口类型,而蓝色框里填写的都是具体的实现类。
  • 集合本身是一个工具,它存放在Java.util包中。在Collection接口定义着单列集合框架中最共性的内容。

1.3 Collection常用方法 

  • public boolean add(E e):添加元素,添加成功返回true,否则false。
  • public void clear():将集合元素清空。
  • boolean remove(E e)
  1. 删除指定元素,删除成功返回true,否则false。
  2. 如果有多个相同的元素,默认只会删除第一个
  • boolean contains(E e):判断集合是否包含指定元素,包含返回true,否则false。
  • public boolean isEmpty():判断集合是否为空(元素个数是否为0),是返回true,否则false。
  • public int size():获得元素的个数。
  • public Object[] toArray()
  1. 将集合中的元素添加到数组返回
  2. 集合转数组
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

public class CollectionDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        Collection<String> coll=new ArrayList<String>();

        //添加元素
        coll.add("aaa");
        coll.add("bbb");
        coll.add("ccc");
        coll.add("ddd");

        System.out.println(coll);
        //删除元素
        System.out.println(coll.remove("aaa"));// true
        System.out.println(coll);

        //判断集合中是否包含元素
        System.out.println(coll.contains("eeee"));//false

        //集合转数组
        Object [] objs=coll.toArray();
        //输出数组中的元素
        System.out.println(Arrays.toString(objs));//[bbb, ccc, ddd]

        //清空集合元素
        coll.clear();
        System.out.println(coll);//[]

        //判断集合是否为空
        System.out.println(coll.isEmpty());//true
    }
}

2.1 迭代器概述 

1.什么是迭代器?

  • 一个用来遍历集合的对象,该对象实现了Iterator接口
  • 对Collection进行遍历的迭代器

2.如何获得迭代器对象?

  • 通过集合对象调用该方法:Iterator<E> iterator()获得迭代器对象。

3. Iterator接口常用方法?

  • boolean hasNext() 判断是否有下一个元素,有返回true,否则false
  • E next() 先将指针下移指向下一个元素,并将当前指针指向位置的元素作为返回值返回。 

2.2 Iterator示例代码  

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

public class IteratorDemo01 {
    public static void main(String[] args) {
        //创建集合对象
        ArrayList<String> list=new ArrayList<>();

        //添加元素
        list.add("aa");
        list.add("bb");
        list.add("cc");
        list.add("dd");

        //使用普通for循环遍历
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        System.out.println("--------------------");
        //获得迭代器对象
        Iterator<String> it=list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
    }
}

2.3 迭代器的好处

  • 屏蔽了众多集合的内部实现,对外提供统一的遍历方式。
  • 所有的单列集合都可以使用迭代器进行遍历。

2.4 迭代器的注意事项

  • hasNext方法仅仅是判断是否有下一个元素,不会移动指针位置。
  • hasNext方法和next方法必须成对出现,调用一次hasNext就对应一次next方法。
  • 使用迭代器遍历集合时不能对集合进行增删操作,否则会抛出异常。
  • java.util.ConcurrentModificationException: 并发修改异常 
  1. 在使用迭代器遍历集合的过程中对集合元素进行了增删操作,则会抛出该异常。

3.1 增强for概述

1.增强for概述

  • JDK1.5新特性
  • 专门用来遍历集合和数组
  • 本质:迭代器

2.增强for格式

  • for(数据类型   变量名:数组名或集合名){ //循环体}

3.2 增强for遍历数组

public class ForEachDemo01 {
    public static void main(String[] args) {
        //定义数组
        int [] arr={1,2,3,4,5,6};

        //使用增强for遍历数组
        for(int num: arr){
            System.out.println(num);
        }
    }
}

 3.3 增强for遍历集合

import java.util.ArrayList;

/*
    增强for遍历集合:存储自定义对象
 */
public class ForEachDemo03 {
    public static void main(String[] args) {
        // 创建集合对象
        ArrayList<Student> list = new ArrayList<>();
        // 添加学生对象
        list.add(new Student("小泽", 20));
        list.add(new Student("小苍", 24));
        list.add(new Student("小波", 26));
        list.add(new Student("小武", 28));
        // 使用增强for
        for (Student stu : list) {
            System.out.println(stu);
            // 修改姓名
            stu.setName("lily");
        }
        System.out.println("----------");
        // 使用增强for
        for (Student stu : list) {
            System.out.println(stu);
        }
    }
}

4.1 泛型在集合中的使用

  • 创建集合同时指定集合存储的数据类型
  • 指定数据类型时,要么指定左边,要么两边都执行相同的数据类型
  • 在JDK1.7之前,必须两边都要指定并且要相同的数据类型
  • JDK1.7之后,指定左边即可
  • 在泛型中没有多态的概念

4.2 泛型在集合中使用的好处

  • 将运行时错误转换为编译期错误,增强了集合的安全性。
  • 省去了数据类型强制转换的麻烦。
  •  示例代码
import java.util.ArrayList;
import java.util.Collection;

public class CollectionDemo04 {
    public static void main(String[] args) {
        //创建集合对象
        ArrayList<String> list=new ArrayList<String>();

        list.add("aa");
        list.add("bb");
        list.add("cc");

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

4.3 泛型的定义与使用

1.泛型的概述

  • JDK1.5新特性。 
  • 泛型可以使用在方法上,上,接口上。 
  • 泛型变量可以理解为是某种数据类型的占位符。
  • 泛型变量还可以理解为是某种数据类型的变量。 
  • 泛型变量的命名规则:只要是合法的标识符就可以,一般使用一个大写字母表示 

   a.常用的泛型变量名有:T type E element K key V value 

2.泛型方法的概念

  • 在定义方法时定义了泛型变量的方法就是泛型方法 。

3.泛型方法的定义格式

  • 修饰符 <T> 返回值类型 方法名(参数列表){} 

4.泛型方法的注意事项 

  • 泛型变量的具体数据类型是由调用者调用方法时传参决定。 
  •  泛型变量的具体数据类型不能是基本数据类型,如果要使用基本数据类型则需要使用对应的包装类类型。
  • 泛型方法示例代码1
public class Demo01 {
    public static void main(String[] args) {
        Integer in=test(456);
        String str=test("bcd");
        Student stu=test(new Student());
        Double d=test(0.5);
        int age=10;
        System.out.println(age);

    }
    //泛型方法
    public static <T> T test(T param){
        T a=null;
        return a;
    }
}
  •  泛型方法示例代码2
/*
     定义一个数组工具类MyArrays ,提供两个成员方法,方法参数接收一个任意类型的数组  
     一个方法的功能是将数组的元素反转.   
      一个方法的功能是将数组的元素拼接成一个字符串返回。    
     字符串格式:"[1,2,3,4,5]" 
 */
public class MyArrays{

    /*
     使用泛型方法实现:方法参数接收一个任意类型的数组
      一个方法的功能是将数组的元素反转.
     */
    public static <T> void reverse(T[] arr){
        for(int i=0,j=arr.length-1;i<j;i++,j--){
            T temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }

    /*
        使用泛型方法:定义一个方法的功能:将数组的元素拼接成一个字符串返回。
        字符串格式:"[1,2,3,4,5]"
     */
    public static <T> String toString(T [] arr){
        //创建可变字符串
        StringBuilder sb=new StringBuilder("[");
        //遍历数组
        for(T t:arr){
            sb.append(t).append(",");
        }
        //删除最后一个元素
        sb.deleteCharAt(sb.length()-1);
        sb.append("]");
        return sb.toString();
    }
}

4.4 泛型类

1. 泛型类概述

  • 在定义类的同时定义了泛型变量的类。 

2.泛型类的定义格式 

  • class 类名<T>{ // 在该类中可以将泛型变量T当成一种数据类型使用。 } 

3.泛型类的注意事项 

  • 泛型类泛型变量的具体数据类型是在创建该类对象时由创建者指定。 
  • 如果创建泛型类对象时没有指定泛型变量的具体数据类型,则默认是Object 
  •  静态方法不能使用类上定义的泛型变量,如果该方法中要使用泛型变量,则需要将该定义为泛型方法。
  • 示例代码 
public class MyArrays<T>{

    /*
      方法参数接收一个任意类型的数组
      一个方法的功能是将数组的元素反转.
     */
    public  void reverse(T[] arr){
        for(int i=0,j=arr.length-1;i<j;i++,j--){
            T temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }

    /*
        将数组的元素拼接成一个字符串返回。
        字符串格式:"[1,2,3,4,5]"
     */
    public  String toString(T [] arr){
        //创建可变字符串
        StringBuilder sb=new StringBuilder("[");
        //遍历数组
        for(T t:arr){
            sb.append(t).append(",");
        }
        //删除最后一个元素
        sb.deleteCharAt(sb.length()-1);
        sb.append("]");
        return sb.toString();
    }
}
//泛型类基本使用
public class Demo {
    public static void main(String[] args) {
        //定义字符串数组
        String[] strs = {"a", "b", "c"};

        //创建MyArrays对象
        MyArrays<String> myArrays01=new MyArrays<>();
        myArrays01.reverse(strs);
        System.out.println(myArrays01.toString(strs));//[c,b,a]

        //创建MyArrays对象
        MyArrays<Integer> myArrays02=new MyArrays<>();
        //创建整型数组
        Integer[] arr={3,4,5,6,7,7};
        myArrays02.reverse(arr);
        System.out.println(myArrays02.toString(arr));//[7,7,6,5,4,3]

        //创建MyArrays对象:不指定泛型变量的具体数据类型
        MyArrays myArrays03=new MyArrays();
    }
}

5.1 泛型接口

1. 泛型接口的概念

  • 在定义接口的同时定义了泛型变量的接口 

2.泛型接口的定义格式 

  • interface 接口名<T>{ // 可以将泛型变量T当成一种数据类型使用 } 

3.泛型接口的实现方式 

  • 方式1:实现接口的同时指定泛型变量的具体数据类型。(不够灵活) 
  •  方式2:实现接口的时不指定泛型变量的具体数据类型,那么此时需要将该实现类定义为泛型类 ,由使用者创建实现类对象时指定泛型变量的数据类型。(推荐使用)
  • 泛型接口示例代码 
/*
   分层开发:
   1.表现层
   2.业务层
   3.数据访问层:直接和数据库打交道,对数据库进行增删改查操作。
 */
public interface Dao<T> {
    //增
    public void save(T t);
    //删
    public void delete(int id);
    //改
    public void update(T t);
    //查
    public T find(int id);
}
/*
    方式1:实现接口的同时指定泛型变量的具体数据类型。
 */
public class ProductDao implements Dao<Product> {
    @Override
    public void save(Product product) {
        System.out.println("增加产品");
    }

    @Override
    public void delete(int id) {

    }

    @Override
    public void update(Product product) {

    }

    @Override
    public Product find(int id) {
        return null;
    }
}
/*
    方式1:实现接口的同时指定泛型变量的具体数据类型。
 */
public class StudentDao implements Dao<Student> {
    @Override
    public void save(Student student) {
        System.out.println("保存学生信息");
    }

    @Override
    public void delete(int id) {
        System.out.println("删除学生信息");
    }

    @Override
    public void update(Student student) {
        System.out.println("更新学生信息");
    }

    @Override
    public Student find(int id) {
        System.out.println("查找学生信息");
        return null;
    }
}
/*
    实现接口的时不指定泛型变量的具体数据类型,那么此时需要将该实现类定义为泛型类,
    由使用者创建实现类对象时指定泛型变量的数据类型。
 */
public  class BaseDao<T> implements Dao<T> {
    @Override
    public void save(T t) {

    }

    @Override
    public void delete(int id) {

    }

    @Override
    public void update(T t) {

    }

    @Override
    public T find(int id) {
        return null;
    }
}
public class Demo {
    public static void main(String[] args) {
        //创建学生对象
        Student stu=new Student();

        //创建StudentDao对象
        StudentDao stuDao=new StudentDao();
        stuDao.save(stu);
        stuDao.update(stu);
        stuDao.delete(1);
        stuDao.find(2);

        //创建产品对象
        Product p=new Product();
        //创建ProduceDao对象
        ProductDao pd=new ProductDao();
        pd.save(p);

        // 创建BaseDao对象指定泛型变量是Student
        BaseDao<Student> baseDao=new BaseDao<>();
        baseDao.save(stu);

        // 创建BaseDao对象指定泛型变量是Product
        BaseDao<Product> baseDao2=new BaseDao<>();
        baseDao2.save(p);

    }
}

6.1 泛型上下限

6.1.1 泛型上下限的引入

需求1:

  • 定义一个方法可以接收任意类型的集合对象
  • 集合对象只能存储Integer或者是Integer的父类数据

需求2:

  • 定义一个方法可以接收任意类型的集合对象
  • 集合对象只能存储Number或者是Number的子类数据

 6.1.2 泛型上下限的格式

1.泛型的上限

  • 格式:<? extends 类>
  • 意义:只能接收该类型及其子类

2.泛型的下限

  • 格式:<? super类>
  • 意义:只能接收该类型及其父类型
  • 注意事项
  • ? 代表泛型通配符,可以匹配任意的类型。
  • 通配符?不能用在泛型方法、泛型类、泛型接口定义上。
  • 通配符?一般不会单独使用,一般都会配合泛型上下限使用。
  • ? 不能在方法体中当成一种数据类型使用 

   a.泛型上限

     ? extends Number:可以接收Number或Number子类类型的数据  

   b.泛型下限     

    ? super Integer : 可以接收Integer或Integer父类类型的数据

import java.util.ArrayList;

public class Demo05 {
    public static void main(String[] args) {
        ArrayList<Number> list01=new ArrayList<>();
        ArrayList<Integer> list02=new ArrayList<>();
        ArrayList<Object> list03=new ArrayList<>();
        print01(list01);
        print01(list02);
        print01(list03);

        print02(list01);
        print02(list02);
        //print02(list03);
    }
    /*
        需求2:定义一个方法可以接收任意类型的集合对象
        集合对象只能存储Number或者是Number的子类数据
     */
    public static void print02(ArrayList<? extends Number> list){

    }
    /*
        需求1:定义一个方法可以接收任意类型的集合对象
        集合对象只能存储Integer或者是Integer的父类数据
     */
    public static void print01(ArrayList<? super Integer> list){

    }
}

猜你喜欢

转载自blog.csdn.net/Huangyuhua068/article/details/81292974