单列集合、泛型最精简的教程

泛型


什么是泛型

泛型是一种未知的数据类型,当我们不知道使用什么数据类型的时候可以使用泛型表示,泛型也可以看做是一个变量用来接收其他人定义的数据类型;

E e:Eelement元素 T t:Type 类型

创建对象使用泛型和不使用的区别

创建对象时不使用泛型:

  • 【好处】:集合不使用泛型,默认类型就是Object,可以存储任意类型的数据
  • 【坏处】:不安全会引发运行时异常
    ArrayList list = new ArrayList();
    list.add("abc");
    list.add(1);

    // 想要使用String类型必须进行向下强制转换(多态)
    // 但是如果不是String类型将会抛出异常
    Iterator it = list.iterator();
    while (it.hasNext()) {
        Object next = it.next();
       	String s = (String) next;
        System.out.println("====>"+s)   
    }

使用泛型创建对象

  • 【好处】:把运行时异常提升到了编译时异常,不需要对象进行强制转换
  • 【坏处】:只能存储规定的类型(利大于弊)
  ArrayList<String> obj = new ArrayList<>();
    obj.add("1");
    obj.add("2");
    obj.add("3");
    for (String s : obj) {
        System.out.println(s.length());
  }

泛型的使用以及定义

1、泛型类的定义

// 定义泛型类
@Data class GenericClass<T> {
    private T userName;
}

@Test public void test01() {
    // 不使用泛型默认为Object类型
    GenericClass g1 = new GenericClass();
    g1.setUserName("张三");
    System.out.println(g1.getUserName());
    // 使用泛型的JavaBean
    GenericClass<Integer> g = new GenericClass<>();
    g.setUserName(10086);
    System.out.println(g.getUserName());
}

<T> 中括号的 “T” 可以为其他的、M、S等等自定义,属性需要和定义的 <T> 的名字一直即可,如果创建该实体,不指定类型默认为Object类型。

2、泛型方法的定义

class GenericMethod {
    // 定义一个泛型的成员方法返回的名字可以随意 T E M 等等
    public <M> void  method01(M params) {
        System.out.println(params);
    }
  	// 静态方法定义
    public static <T> T methodStatic(T ts) {
      System.out.println(ts);
        return ts;
    }
}

---- 测试定义的泛型方法
@Test public void testMethod() {
    GenericMethod method = new GenericMethod();
    method.method01(1);
    method.method01("abc");
    method.method01(true);
    GenericMethod.methodStatic(1,"2",'c',true);
}

格式:访问修饰符 <泛型> void|泛型 方法名(泛型 参数名称)

3、泛型的接口以及实现类定义

接口定义:

interface GenericInter<T>{

    public abstract void interMethod01(Integer i);

    public abstract void interMethod02(T t);
}

【注意事项】

  1. 泛型接口中的方法若想使用泛型参数,必须指定接口为泛型的。

  2. 泛型接口中仍然可以使用非泛型的成员方法。

实现类定义:

实现类定义有两种方式,1.直接在实现接口的时候指定泛型的类型,2.在实现接口的同时指定实现类的泛型和接口一致,在创建对象的时候指定类型。如果都不指定默认为object

// 实现类直接指定
class GenericInterImpl implements GenericInter<String>{
    @Override
    public void interMethod01(Integer i) {
        System.out.println(i);
    }

    @Override
    public void interMethod02(String s) {
        System.out.println(s);
    }
}
-----
// 实现类同样使用泛型,创建对象指定泛型类型
class GenericInterImplement<T> implements GenericInter<T> {
    @Override
    public void interMethod01(Integer i) {
        System.out.println(i);
    }
    @Override
    public void interMethod02(T t) {
        System.out.println(t);
    }
}
-----
/**
 * 测试定义的泛型接口
 */
@Test public void testInter() {
    // 实现类指定泛型类型
    GenericInterImpl generic = new GenericInterImpl();
    generic.interMethod01(1);
    generic.interMethod02("2");

    // 创建对象时指定泛型类型
    GenericInter<Integer> ge = new GenericInterImplement<>();
    ge.interMethod02(1);
    ge.interMethod01(2);
}

泛型的通配符 ?

泛型的通配符:【?】
作用:一般用于指定传入的集合属于什么类型,不能创建对象使用,只能作为参数使用。

public static void main(String[] args) {
      ArrayList<Integer> list1 = new ArrayList<>();
      list1.add(1);
      list1.add(2);

      ArrayList<String> list2 = new ArrayList<>();
      list2.add("a");
      list2.add("b");

      printArray(list1);
      printArray(list2);
}
// 使用泛型通配符?只能作为方法的参数使用
// 我们此时不知道到底使用什么类型进行接收使用?
public static void printArray(List<?> list) {
    for (Object o : list) {
        System.out.println(o);
    }
}

通配符的高级用法

  • 泛型的上限限定: ? extends T --> 代表【?】只能是【T本身 || T类型的子类】
  • 泛型的下限限定: ? super T --> 代表【?】只能是【T本身 || T类型的父类】
		@Test public void test() {
        // Integer extends Number -- Number extends Object
        List<Integer> integers = new ArrayList<>();
        List<String> strings = new ArrayList<>();
        List<Number> numbers = new ArrayList<>();
        List<Object> objects = new ArrayList<>();

        // 上限限定:参数只能是子类或者本类
        getElementsUnderNumber(integers);
//      getElementsUnderNumber(strings);    编译报错
        getElementsUnderNumber(numbers);
//      getElementsUnderNumber(objects);    编译报错


        // 下限限定:参数之类是父类或者本类
//      getElementsSuperNumber(integers);   编译报错
//      getElementsSuperNumber(strings);    编译报错
        getElementsSuperNumber(numbers);
        getElementsSuperNumber(objects);


    }

    // 上限规定:list只能是Number本身或者Number的子类
    public void getElementsUnderNumber(List<? extends Number> list) { }

    // 下限规定:list只能是Number本身或者Number的父类
    public void getElementsSuperNumber(List<? super Number> list) { }

集合


集合中的总体体系 — 分为单列集合Collection接口双列集合Map接口,现在主要记录的是单列集合。

单列集合: 又划分为List、Set集合,同样这两个都是接口,下面有几个实现类。

  • List特性:有序,可重复,实现类如下:

    • ArrayList:动态数组结构, 查找快,增删慢
    • linkendList:链表结构,增删快,查找慢
    • Vector:和【ArrayList】一样的实现,但是线程安全,所以效率低下
  • Set特性:无序,不可重复。

    • HashSet:底层数据结构是一个哈希表通过 hashcode() 和equals()来保证元素的唯一性,线程不安全 存取速度快
    • treeSet:底层数据结构是一个红黑树 默认对元素进行自然排序,如果在比较的时候两个对象返回值为0,那么元素重复。
    • linkendSet

共性方法: 单列集合的所有共性方法,适合所有的单列集合,其实无法就是增删改查CRUD。

方法名方法作用
add(E e)添加元素
remove(E e)移除元素
clear()清空元素
addAll(Collection<? extends E> e)添加另外一个集合的所有内容
contains(E e)是否包含
isEmpty()是否为空
size()获取大小长度
toArray()转化数组
iterator()返回迭代器
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值