【Java】(二十一)泛型类/接口/方法/集合,Set接口与实现类(HashSet、TreeSet)

续上一节Java集合框架,Collection接口,List接口与实现类,依旧是Java集合的内容。

4 泛型

  1. Java泛型是JDK1.5中引入的一个新特性,其本质是参数化类型,把类型作为参数传递。
    在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型。
    【类似于模板,先不定义类型,在使用时在限定类型。比如同一个泛型方法,可以用于整数和都浮点数运算】
  2. 这种参数类型可以用在类、接口和方法中,分别被称为泛型类、泛型接口、泛型方法
  3. 语法:<T,...>T称为类型占位符,表示一种引用类型。可以写多个参数,逗号隔开<T,K,E>
  4. 运用泛型的好处:
    (1)提高代码的重用性
    (2)防止类型转换异常,提高代码的安全性

4.1 泛型类

  1. 泛型类创建语法:类名 <T>
  2. 可以创建变量T t;但是不能实例化T t1 = new T();(有可能构造函数私有等原因)
  3. 泛型只能使用引用类型【可以是Integer,不能是int】
  4. 不同泛型类型对象之间不能相互赋值。
package study.generic;

//定义泛型类语法:类名<T>
public class MyGenericClass<T> {
    //1.使用泛型类创建成员变量
    T t;
    //T t2 = new T();//编译报错:类型参数'T'不能直接实例化

    //2.作为方法形式参数
    public void show(T t){
        System.out.println("泛型参数:"+t);
    }

    //3.作为返回值
    public T getT(){
        return t;
    }
}

4.2 泛型接口

  1. 泛型接口语法:接口名<T>
  2. 不能泛型静态常量。

泛型接口:

package study.generic;

public interface MyGenericIn<T> {
//    T t;//编译报错:不能从静态上下文引用
    String name = "louis";

    //接口只有规范,不写方法体
    T service(T t);
}

泛型接口的两种实现类:

  1. 继续使用泛型
package study.generic;

public class InClass1<T> implements MyGenericIn<T> {
    @Override//重写快捷键【Alt+Insert】
    public T service(T t) {
        return t;
    }
}
  1. 在实现类中指定类型
package study.generic;

public class InClasses<String> implements MyGenericIn<String> {
    @Override
    public String service(String string) {
        return string;
    }
}

4.3 泛型方法

  1. 定义在普通类中,泛型方法的语法修饰符 <T> 返回类型 方法名(T t)

普通类中的泛型方法:

package study.generic;

//普通类
public class GenMethodClass {
    //泛型方法
    public <T> void show(T t){
        System.out.println("泛型方法" + t);
    }

    public <T> T show2(T t){
        System.out.println("泛型方法" + t);
        return t;
    }
}

4.4 泛型集合

  1. 概念:参数化类型、类型安全的集合。强制集合元素的类型必须一致,可以避免强制类型转换时出错。
  2. 特点:
    (1)编译时即可检查,而非运行时抛出异常
    (2)访问时,不必类型转换(拆箱)
    (3)不同泛型之间应用不能相互赋值,泛型不存在多态

普通集合:
在这里插入图片描述
泛型集合:
在这里插入图片描述

4.5 测试类

package study.generic;

import java.util.ArrayList;

public class mainGenericText {
    public static void main(String[] args) {
        System.out.println("1.泛型类");
        MyGenericClass<String> c1 = new MyGenericClass<String>();
        c1.t = "Hello,Java";
        c1.show("Hello,World");
        System.out.println(c1.getT());

        MyGenericClass<Integer> c2 = new MyGenericClass<>();
        c2.show(250);
//        MyGenericClass<int> c3 = new MyGenericClass<int>();//编译报错:类型参数不能是原始类型
//        c2 = c1;//不同类ing不能互相赋值

        System.out.println("2.泛型接口的实现类调用");
        //需要指名泛型类
        InClass1<Integer> c3 = new InClass1<>();
        System.out.println(c3.service(30));
        //已定义好的接口实现类
        InClasses<Object> c4 = new InClasses<>();
        System.out.println(c4.service("Hello,Java"));

        System.out.println("3.泛型方法");
        GenMethodClass c5 = new GenMethodClass();
        c5.show("Java");
        System.out.println(c5.show2("Halo"));

        System.out.println("4.泛型集合");
        ArrayList<String> s1 = new ArrayList<>();
        s1.add("Chanel");
        s1.add("LV");
//        s1.add(100);//编译报错
        for(String s:s1){
            System.out.println(s);
        }
    }
}

/*
1.泛型类
泛型参数:Hello,World
Hello,Java
泛型参数:250
2.泛型接口的实现类调用
30
Hello,Java
3.泛型方法
泛型方法Java
泛型方法Halo
Halo
4.泛型集合
Chanel
LV
 */

5 Set接口与实现类

  1. 特点:无序、无下标、元素不可重复
  2. 方法:全部继承自Collection中的方法。
    增、删、遍历、判断完全一致。
    构造方法因为实现类不同略有不同Set<String> s1 = new HashSet<>();
  3. 两种实现类:HashSet和TreeSet。

5.1 HashSet类

  1. 存储结构:哈希表(数组+链表+红黑树)
  2. 存储过程(怎么判断元素是否重复):
    ①根据hashCode方法计算保存的位置,如果位置为空,直接保存;
    ②若不为空,再执行equals方法,如果equals为true,则认为是重复,否则形成链表。
    【对于自定义类,需要重写方法】例如Person类(属性名字、年龄)
    在这里插入图片描述
  3. 特点
    基于HashCode计算元素存放位置:
    (1)利用31这个质数,减少散列冲突
    (2)提高执行效率。31*i=(i << 5)-i转为移位操作。
    当存入元素的哈希码相同时,会调用equals进行确认,如果结果为true,则拒绝后者存入
  4. 方法(同Collection)

5.2 TreeSet类

  1. 存储结构:红黑树(二叉排序平衡)
  2. 创建集合:TreeSet<String> treeSet = new TreeSet<>()
  3. 方法(添加、删除、遍历、判断同Collection)
  4. 特点:
    (1)基于排列顺序实现元素不重复。
    (2)实现SortedSet接口,对集合元素自动排序。
    (3)元素对象的类型必须实现Comparable接口,指定排序规则
    (4)通过CompareTo方法确定是否为重复元素。
    在这里插入图片描述查源码知道,包类型都自动继承Comparable接口,并且Comparable接口里面只有一个方法CompareTo方法。
  5. TreeSet集合的使用方法(自定义排序规则)
    (1)对象类型继承Comparable接口,重写CompareTo方法来制定排序规则。
    (2)Comparator比较器实现定制比较.

5.2.1 Comparable接口

int compareTo(T o)将此对象与指定的对象进行比较,返回一个负整数、零或一个正整数,因为这个对象小于、等于或大于指定的对象。

重写对象方法:

package generic;

public class Person implements Comparable<Person> {
    String name;
    int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override//重写比较方法,先按姓名比较再按年纪比较
    public int compareTo(Person o) {
        int n1 = this.getName().compareTo(o.getName());
        int n2 = this.getAge()-o.getAge();
        return n1==0?n2:n1;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

创建集合并添加对象:

package generic;

import java.util.TreeSet;

public class TreeSetText {
    public static void main(String[] args) {
        //创建集合
        TreeSet<Person> pe = new TreeSet<>();
        //创建对象
        Person p1 = new Person("Louis", 22);
        Person p2 = new Person("LV", 20);
        Person p3 = new Person("Chanel", 19);
        //添加对象到集合
        pe.add(p1);
        pe.add(p2);
        pe.add(p3);
        pe.add(new Person("LV", 20));//因为重写了比较方法才可以判断出重复
        System.out.println(pe.toString());
        //删除对象
        pe.remove(p1);
        pe.remove(new Person("LV", 20));//因为重写了比较方法才可以判断出重复存在
        System.out.println(pe.toString());
    }
}

/*
[Person{name='Chanel', age=19}, Person{name='LV', age=20}, Person{name='Louis', age=22}]
[Person{name='Chanel', age=19}]
 */

5.2.2 Comparator比较器

Comparator实现定制比较(比较器),就可以不再需要实现Comparable接口比较功能。

package generic;

/*
要求:使用Treeset集合实现字符串按照长度进行排序
comparator接口实现定制比较
 */

import java.util.Comparator;
import java.util.TreeSet;

public class Demo01 {
    public static void main(String[] args) {
        //创建集合并使用comparator接口定制比较
        TreeSet<String> ts = new TreeSet<>(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                int n1 = o1.length()-o2.length();
                int n2 = o1.compareTo(o2);
                return n1==0?n2:n1;//长度相等判断再是否一致
            }
        });

        ts.add("Balenciaga");
        ts.add("Chanel");
        ts.add("Louis");
        ts.add("Burberry");

        System.out.println(ts);//[Louis, Chanel, Burberry, Balenciaga]
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值