JavaSE阶段学习02:Collection、泛型

JavaSE阶段学习02:Collection、泛型

主要内容

  • Collection集合
  • 迭代器
  • 增强for(foreach)
  • 泛型

教学目标

  • [ ] 能够说出集合与数组的区别
  • [ ] 说出Collection集合的常用功能
  • [ ] 能够使用迭代器对集合进行取元素
  • [ ] 能够说出集合的使用细节
  • [ ] 能够使用集合存储自定义类型
  • [ ] 能够使用foreach循环遍历集合
  • [ ] 能够使用泛型定义集合对象
  • [ ] 能够理解泛型上下限
  • [ ] 能够阐述泛型通配符的作用

第一章 Collection集合

1.1 集合概述

什么是集合
    * 就是一个容器,可以存储多个数据。

数组和集合的区别
    * 数组的长度固定,集合的长度是可变。
    * 数组可以存储基本数据类型,也可以存储引用数据类型,集合只能存储引用数据类型
    * 数组只能存储同一种数据类型,而集合可以存储多种数据类型(不建议)

集合的分类
    * 单列集合:Collection:每次存储元素时只存储一个
    * 双列集合:Map:每次存储元素时存储两个元素。

1.2 Collection集合体系

* Colletion:是所有单列的集合的父类。
    * List
        * ArrayList
        * LinkedList
        * Vector(过时了)
    * Set
        * HashSet
        * LinkedHashSet

1.3 Collection 常用方法

public boolean add(E e) 添加元素
public void clear()     清空集合中的元素
boolean remove(E e)     删除指定的元素,删除成功返回true,否则false,只删除第一次出现的元素。
boolean contains(E e)   判断集合中是否包含指定的元素,包含返回true,否则false
public boolean isEmpty()  判断集合是否为空(元素个数是否等于零),为空返回true,否则false
public int size()       获得集合元素的个数
public Object[] toArray()  将集合转换为数组
  • 示例代码
public class CollectionDemo02 {
    public static void main(String[] args){
        // 创建集合对象
        Collection<String> co = new ArrayList<>();
        // 添加元素
        co.add("aa");
        co.add("bb");
        co.add("cc");
        co.add("aa");
        System.out.println(co); // [aa, bb, cc, aa]
        // 集合转数组
        Object[] objs =  co.toArray();
        System.out.println(Arrays.toString(objs)); // [aa, bb, cc, aa]

        // 删除指定元素:aa
        System.out.println(co.remove("aa")); // true
        System.out.println(co);

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


        // 清空集合中的元素
        co.clear();
        /*co.add("dd");*/
        System.out.println(co);

        // 判断集合是否为空
        System.out.println(co.isEmpty());
        if (co.isEmpty()){

        }
    }
}

1.4 使用集合存储自定义对象

第二章 Iterator迭代器

2.1 什么是迭代器

什么是迭代器
    * 一个用来遍历集合的对象,该对象是实现了Iterator接口。
    * 只要是实现了Iterator接口的对象都是迭代器对象。

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

Iterator接口中的常用方法
    * boolean hasNext(); 判断是否有下一个元素,如果有则返回true,否则false
    * E next(); 先将指针下移指向下一个元素,然后将当前指针指向位置的元素作为返回值。

迭代器的使用注意事项
    * java.util.NoSuchElementException:没有元素异常
        * 如果没有元素可迭代了仍然调用next方法获得元素,则会抛出该异常。

2.2 迭代器的好处

1. 屏蔽了众多集合的内部实现,对外提供统一的遍历方式。
2. 只要是单列集合都可以使用迭代器遍历

2.3 Iterator常用方法

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

2.4 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");

        // 使用循环改进
        Iterator<String> it =  list.iterator();
        while(it.hasNext()){ // true
            System.out.println(it.next());
        }

        /* 没有使用循环
        // 使用迭代器遍历集合
        Iterator<String> it =  list.iterator(); //  new Itr();

        System.out.println(it.hasNext()); // true
        System.out.println(it.next());    // aa

        System.out.println(it.hasNext()); // true
        System.out.println(it.next());    // bb

        System.out.println(it.hasNext()); // true
        System.out.println(it.next());    // cc

        System.out.println(it.hasNext()); // true
        System.out.println(it.next());    // dd

        System.out.println(it.hasNext()); // false
        System.out.println(it.next());    // dd
        */

        // 普通for遍历
       /* for(int index = 0;index < list.size();index++){
            // 根据索引获得集合
            String str = list.get(index);
            System.out.println(str);
        }*/
    }
}

第三章 增强for(foreach)

3.1 增强for概述

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

3.2 增强for格式

for(数据类型 变量名: 数组名或集合名){

}

3.3 增强for示例代码

练习1:遍历数组
public class ForEachDemo01 {
    public static void main(String[] args){
        // 定义一个整型数组
        int[] arr = {1,2,3,4,5,6};
        // 使用增强for遍历数组
        /*
         for(数据类型 变量名: 数组名或集合名){

        }
         */
        for (int num : arr){
            System.out.println(num);
            num += 10;
        }
        System.out.println("------------");
        for(int num:arr){
            System.out.println(num);
        }
    }
}

练习2:遍历集合
public class ForEachDemo02 {
    public static void main(String[] args){
        // 增强for遍历集合:集合存储自定义对象
        test01();
        // 增强for遍历集合:集合存储字符串
        test02();
    }

    /*
        增强for遍历自定义对象
     */
    public static void test02(){
        // 创建集合对象
        ArrayList<Student> list = new ArrayList<>();
        list.add(new Student("小泽"));
        list.add(new Student("小苍"));
        list.add(new Student("小波"));
        list.add(new Student("小玉玉"));

        // 使用增强for遍历
        for(Student stu: list){
            System.out.println(stu);
            stu.setName("小野");
        }
        System.out.println("-------------");
        // 使用增强for遍历
        for(Student stu: list){
            System.out.println(stu);
        }
    }

    // 增强for遍历集合
    public static void test01(){
        // 创建集合对象
        ArrayList<String> list = new ArrayList<>();
        list.add("aa");
        list.add("bb");
        list.add("cc");
        list.add("dd");

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

第四章 泛型

3.1 泛型在集合中使用

泛型的概述
    * JDK1.5新特性。
    * 泛型可以使用在方法中,类上,接口上。

泛型在集合中使用的好处
    * 将运行期错误转换为编译器错误,增强了集合的安全性。
    * 避免了类型强制转换的麻烦。

泛型在集合中的使用注意事项
    * 在泛型中,没有多态的概念,要么指定左边,要么两边都指定相同的数据类型。
    * 在JDK1.7之前,必须两边都指定相同的数据类型。
  • 示例代码
public class CollectionDemo {
    public static void main(String[] args){
        // 创建集合对象
        ArrayList<String> list = new ArrayList<>();
        list.add("aaa");
        list.add("bbb");
        list.add("ccc");
        // list.add(123);

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

        // 遍历集合
        for (Object obj:list) {
            // 向下转型为字符串
            String str = (String) obj;

            System.out.println(str.length());
        }
    }
}

3.2 泛型的定义与使用(了解)

3.2.1 泛型方法

泛型方法引入
  • 定义一个方法接收一个任意类型的参数,返回值类型与实际参数类型一致。
什么是泛型
    * 数据类型参数化。

 泛型方法的引入
    * 定义一个方法接收一个任意类型的参数,返回值类型与实际参数类型一致。

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

泛型方法的概念
    * 在定义方法时定义了泛型变量的方法则称为泛型方法。

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

泛型方法的注意事项
    * 泛型变量的具体数据类型是在调用该方法时由调用者传递参数决定。
        * 参数是什么类型,则泛型变量的具体数据类型就是什么类型。
    * 泛型变量的具体数据类型不能是基本数据类型,如果要使用基本数据类型,要使用对应的包装类类型。
示例代码
public class Demo01 {
    public static void main(String[] args){
        String str =  test("abc");
        Integer in = test(123);

        Student stu = test(new Student());

        int age = 100;
        System.out.println(age);
    }

    public static void sum(int a,int b){

    }

    /*
        泛型方法
     */
    public static <T> T test(T param){

        return param;
    }
}
泛型方法练习
- 定义一个数组工具类MyArrays
- 提供两个成员方法,方法参数接收一个任意类型的数组
  - 一个方法的功能是将数组的元素反转.
  - 一个方法的功能是将数组的元素拼接成一个字符串返回。
    - 字符串格式:"[1,2,3,4,5]" 
  • 代码实现
/**
 - 提供两个成员方法,方法参数接收一个任意类型的数组
     - 一个方法的功能是将数组的元素反转.
     - 一个方法的功能是将数组的元素拼接成一个字符串返回。
     - 字符串格式:"[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();
    }
}

public class Demo02 {
    public static void main(String[] args){
        // 创建字符串数组
        String[] strs = {"a","b","c"};
        // 创建整型数据
        Integer[] arr = {1,2,3,4,5,6};
        /*
        // 创建数据工具类型对象
        MyArrays myArrays = new MyArrays();
        myArrays.reverse(strs);*/

        System.out.println("反转前:"+ Arrays.toString(strs));
        // 反转字符串数组元素
        MyArrays.reverse(strs);
        System.out.println("反转后:" + MyArrays.toString(strs));

        System.out.println("反转前:"+MyArrays.toString(arr));
        // 反转整型数组元素
        MyArrays.reverse(arr);
        System.out.println("反转后:"+MyArrays.toString(arr));

    }
}

3.2.2 泛型类

什么是泛型类
    * 在类定义时定义了泛型变量的类就是泛型类

泛型类的定义格式
    * class 类名<T>{
        // 可以将泛型变量T当成一种数据类型使用
     }

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

    // 一个方法的功能是将数组的元素反转.
    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 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 void xxx(){

    }
}

public class Demo01 {
    public static void main(String[] args){
        // 创建字符串数组
        String[] strs = {"a","b","c"};
        // 创建整型数据
        Integer[] arr = {1,2,3,4,5,6};
        // 创建泛型类对象
        MyArrays<String> myArrays01 = new MyArrays<>();
        // 此时通过对象myArrays01调用方法,方法中的泛型变量的具体数据类型是:String
        myArrays01.reverse(strs);


        // 创建泛型类对象
        MyArrays<Integer> myArrays02 = new MyArrays<>();
        // 此时通过对象myArrays02调用方法,方法中的泛型变量的具体数据类型是:Integer
        myArrays02.reverse(arr);


        MyArrays myArrays03 = new MyArrays();
    }
}

3.2.3 泛型接口

什么是泛型接口
    * 在定义接口的同时定义了泛型变量的接口

泛型接口的定义格式
    * interface 接口名<T>{
        // 将泛型变量T当成一种数据类型使用
    }

泛型接口的实现方式
    * 方式1:实现接口的同时指定泛型变量的具体数据类型(不推荐使用,不够灵活)
    * 方法2:实现接口时不指定泛型变量的具体数据类型,将实现类定义为泛型类,
            由使用者创建泛型类对象时指定泛型变量的具体数据类型。(推荐使用)
  • 示例代码
/**
    Dao:数据访问层接口
    泛型接口

    表现层
    业务层
    数据访问层:直接跟数据库打交道,对数据库执行增删改查操作的。
 */
public interface Dao<T>{
    // 增
    public void save(T t);
    // 改
    public void update(T t);
}

/**
 	实现接口的同时指定泛型变量的具体数据类型
 */
public class ProductDao implements Dao<Product> {
    @Override
    public void save(Product product) {
        System.out.println("保存产品信息...");
    }

    @Override
    public void update(Product product) {
        System.out.println("更新产品信息...");
    }
}

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

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

/**
 实现接口时不指定泛型变量的具体数据类型,将实现类定义为泛型类,
    由使用者创建泛型类对象时指定泛型变量的具体数据类型。
 */
public class BaseDao<T> implements Dao<T> {
    @Override
    public void save(T t) {

    }

    @Override
    public void update(T t) {

    }
}

public class Demo01 {
    public static void main(String[] args){
        // 创建学生对象
        Student stu = new Student();
        // 创建Dao接口的实现类对象
        StudentDao stuDao = new StudentDao();
        // 保存学生
        stuDao.save(stu);

        // 创建产品对象
        Product p = new Product();
        // 创建Dao接口的实现类对象
        ProductDao pdDao = new ProductDao();
        // 保存产品
        pdDao.save(p);


        // 创建BaseDao对象
        BaseDao<Student> baseDao01 = new BaseDao<>();
        // 保存学生
        baseDao01.save(stu);

        // 创建BaseDao对象
        BaseDao<Product> baseDao02 = new BaseDao<>();
        baseDao02.save(p);
    }
}

3.3 泛型上下限(了解)

3.3.1 泛型上下限引入

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

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

3.3.2 泛型上下限格式

? : 泛型通配符  代表可以匹配任意数据类型。
泛型上限:? extends Number 可以接收Number或Number的子类类型的数据
泛型下限:? super Integer  可以接收Integer或Integer的父类类型的数据。

泛型通配符注意事项
    * ? 一般不会单独使用,一般会结合泛型上下限使用。
    * ? 不能用来定义泛型方法,泛型类,泛型接口

? 和 泛型变量T 的区别
    ? 不需要定义就可以使用,T 需要先定义再使用
    ? 在方法体不能当成一种数据类型使用,泛型变量T可以当成一种数据类型使用。

3.3.3 示例代码

public class Demo01{
    public static void main(String[] args){

        ArrayList<String> list01 = new ArrayList<>();
        ArrayList<Integer> list02 = new ArrayList<>();
        ArrayList<Object> list03 = new ArrayList<>();
        ArrayList<Number> list04 = new ArrayList<>();
        ArrayList<Long> list05 = new ArrayList<>();

        // test01(list01); // 编译失败
        test01(list02); // 编译通过
        test01(list03); // 编译通过
        test01(list04); // 编译通过

        // test02(list01);  // 编译失败
        test02(list02);  // 编译通过
        // test02(list03);  // 编译失败
        test02(list04);  // 编译通过
        test02(list05);  // 编译通过*/
    }


    public static void test02(ArrayList<? extends Number> list) {

    }

    public static void test01(ArrayList<? super Integer> list) {

    }

}

小结

Collection:所有单列集合的父类
	Collection集合的继承体系
		Collection:
			List:ArrayList,LinkedList,Vector(过时)
			Set:HashSet,LinkedHashSet
	Collection集合常用方法
		void add(E e);添加元素
		void clear();清空元素
		boolean remove(Object e);删除指定的元素,成功返回true,否则false
		boolean isEmpty(); 判断集合是否为空,空返回true否则false
		Object[] toArray();集合转数组
		boolean contains(Object e);判断集合中是否包含指定元素,包含返回true,否则false。
		int size();获得元素个数
		
迭代器概述
	一个用来遍历集合的对象
	该对象实现了Iterator接口

如何获得迭代器对象
	* 通过调用集合对象iterator()方法获得。
	
Iterator接口常用方法
	boolean hasNext(); 判断是否有下一个元素,有返回true,否则false
	E next(); 将指针下移指向下一个元素,并返回当前指针指向位置的元素。
	
迭代器的好处
	* 屏蔽了众多集合的内部实现,对外提供统一的遍历方式。
	* 所有的单列集合都可以使用迭代器遍历。

增强for概述
	* JDK1.5新特性,专门用来遍历集合和数组的,本质是:迭代器
增强for格式
	* for(数据类型 遍历名:数组名或集合名){}
	* 注意事项:在遍历集合过程中不能对集合元素进行增删操作,否则会出现并发修改异常。
泛型概述
	* JDK1.5新特性
	* 泛型可以使用在方法上,类上,接口上。
	* 泛型变量可以理解为是一种数据类型的占位符,也可以理解为是一种数据类型的变量。
	
泛型方法概述:在定义方法时定义了泛型变量的类
泛型方法的定义格式:修饰符 <泛型变量T> 返回值类型  方法名(参数列表){}
泛型方法注意事项:泛型变量的具体数据类型是由调用者调用方法传参决定。

泛型类概述:在定义类时定义了泛型变量的类
泛型类定义格式:class 类名<泛型变量T>{ }
泛型类注意事项
	泛型类上泛型变量的具体数据类型是创建对象时由使用者指定,如果没有指定,则默认是Object
	静态方法不能使用类上定义的泛型变量,如果要使用,则需要将该方法定义为泛型方法。
	
泛型接口概述:在定义接口时定义了泛型变量的接口
泛型接口的定义格式:interface 接口名<泛型变量T>{}
泛型接口的实现方式
	实现接口同时指定泛型变量的具体数据类型(不够灵活)
	实现接口时不指定泛型变量的具体数据类型,将该实现类定义泛型类,由使用者创建实现类对象时指定泛型变量的		具体数据类型。	
	
泛型上下限
	? 通配符,可以匹配任意类型数据
	? extends Number: 可以接收Number或Number子类数据
	? super Integer: 可以接收Integer或Integer的父类数据

转载于:https://my.oschina.net/caijhoo/blog/2252693

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值