集合(2)--泛型

泛型(Generic)概述

  • 泛型:是一种未知的数据类型,当我们不知道使用什么数据类型的时候,可以使用泛型;
  • 创建集合对象,不使用泛型
    好处:集合不使用泛型,默认的类型就是Object类型,可以存储任意类型的数据;
    弊端:不安全,会引发异常
public static void show(){
        //不使用泛型创建集合对象
        ArrayList list = new ArrayList();
        list.add(1);
        list.add("abc");

        //使用迭代器遍历list集合
        Iterator it= list.iterator();
        while (it.hasNext()){
            //想要使用String类特有地方啊,需要向下转型,因为list集合中保存的是Object对象
            //但无法把Integer对象强转成String对象,会抛出ClassCastException异常
            String s = (String) it.next();
            System.out.println(s.length());
        }
    }
  • 创建集合对象,使用泛型
    好处:
    1)避免了类型转换的问题,存储的是什么类型,取出的就是什么类型
    2)把运行期异常(代码运行之后会抛出的异常),提升到了编译期(写代码的时候会报错)
    弊端:泛型是什么类型,则只能存储什么类型

泛型的定义与使用

定义一个泛型类

  • 泛型是一个未知的数据类型,当我们不确定什么数据类型的时候,可以使用泛型,
    泛型可以接收任意的数据类型(如:Integer、String),创建对象的时候要确定泛型的类型
public class GenericClass<E> {
    private E name;

    public E getName() {
        return name;
    }

    public void setName(E name) {
        this.name = name;
    }
}
//使用
public static void main(String[] args) {
        //创建GenericClass对象,泛型使用Integer类型
        GenericClass<Integer> generic = new GenericClass<>();
        generic.setName(20);
    }

含有泛型的方法

  • 定义含有泛型的方法:泛型定义在方法的修饰符和返回值类型之间
  • 格式:
    修饰符 <泛型> 返回值类型 方法名 (参数列表(使用泛型)){
    方法体;
    }
  • 含有泛型的方法,在调用方法的时候确定泛型的类型;(传递什么类型的参数,泛型就是什么类型)
public <E> void method(E e){
        System.out.println(e);
}
//静态方法
public static <E> void method(E e){
        System.out.println(e);
}

定义和使用含有泛型的接口

  • 含有泛型的接口,第一种使用方式:定义接口的实现类,实现接口,定义泛型的类型
  • 使用举例:
    使用举例
//定义一个泛型接口
public interface GenericInterface<E> {
    public abstract void method(E e);
}
//定义泛型接口实现类
public class GenericInterfaceImpl implements GenericInterface<String> {
    @Override
    public void method(String s) {
        System.out.println(s);
    }
}
  • 含有泛型的接口,第二种使用方式:接口使用什么泛型,实现类就使用什么泛型,类跟着接口走
  • 就相当于定义了一个泛型类,创建对象的时候确定泛型的类型
  • 使用举例:
    使用举例
//定义实现类
public class GenericInterfaceImpl2<E> implements GenericInterface<E> {
    @Override
    public void method(E e) {
        System.out.println(e);
    }
   }
//使用
public static void main(String[] args) {
        GenericInterfaceImpl2<String>  genericInterfaceImpl2 = new GenericInterfaceImpl2<>();
        genericInterfaceImpl2.method("abc");//泛型为String类型
    }

泛型通配符

  • 当使用泛型类或接口时,传递的数据中,泛型类型不确定,可以通过通配符<?>表示。但是一旦使用泛型的通配符后,只能使用Object类中的共性方法,集合中元素自身方法无法使用。
  • 泛型通配符:不知道使用什么类型来接收时,此时可以使用?,?表示未知通配符;
    此时只能接受数据,不能往该集合中存储数据。
    -使用方法: 不能创建对象使用,只能作为方法的参数使用
public class Test {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("abc");

        ArrayList<Integer> list2= new ArrayList<>();
        list2.add(2);

        printArray(list1);//报错,String类型不是Object类型
        printArray(list2);//报错,Integer类型不是Object类型
        
        printArray1(list1);//正确
        printArray1(list2);//正确
    }
    
    //注意:泛型没有继承概念,<>中写的是什么类型,传给方法的就必须是什么类型
    public static void printArray(ArrayList<Object> list){
        //使用迭代器遍历集合
        System.out.println(list.toString());
    }
    
    //使用泛型通配符?来接收数据类型
    public static void printArray1(ArrayList<?> list){
        //使用迭代器遍历集合
        System.out.println(list.toString());
    }
}

通配符的高级使用–受限泛型

  • 泛型的上限
    1)格式:类型名称 <? extends 类 > 对象名称
    2)意义:只能接收该类型及其子类
  • 泛型的下限
    1)格式:类型名称 <? super 类 > 对象名称
    2)意义:只能接收该类型及其父类
public class Test {
    public static void main(String[] args) {
        ArrayList<String> list1 = new ArrayList<>();
        ArrayList<Integer> list2= new ArrayList<>();
        ArrayList<Number> list3 = new ArrayList<>();
        ArrayList<Object> list4= new ArrayList<>();
        
        //继承关系:Integer>Number>Object
        //           String>Object
        getElement1(list1);//报错,String不是Number的子类
        getElement1(list2);//正确
        getElement1(list3);//正确
        getElement1(list4);//报错Object是Number的父类
        
        getElement2(list1);//报错,String不是Number的父类
        getElement2(list2);//报错,Integer是Number的子类,不是它的父类
        getElement2(list3);//正确
        getElement2(list4);//正确
    }
      //泛型的上限:此时的泛型?必须是Number类或Number类型的子类
    public static void getElement1(Collection<? extends Number> coll){}

    //泛型的下限:此时的泛型?必须是Number类或Number类的父类
    public static void getElement2(Collection<? super Number> coll){}
}

和集合相关的数据结构

  • 栈(stack):先进后出
  • 队列(queue):先进先出
  • 数组(Array):查询快,增删慢
       查询快:数组地址是连续的,可以通过首地址找到数组,通过索引找到某一元素;
       增删慢:数组长度是固定的,想要增加/删除一个元素,必须创建一个新数组,把源数组元素复制过来;
  • 链表:查询慢,增删快
       查询慢:链表中地址是不连续的,每次查询元素,都必须从头开始;
       增删快:链表结构,增加/删除一个元素,对链表的整体结构没有影响,所以增删快;
  • 红黑树:趋近于平衡二叉树,查询的速度非常快,查询叶子节点最长路径不超过最小路径的2倍
       性质1. 节点是红色或黑色。
       性质2. 根节点是黑色。
       性质3. 每个叶节点(空节点)是黑色的。
       性质4. 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
       性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值