【Java】—— 泛型:泛型的理解及其在集合(List,Set)、比较器(Comparator)中的使用

目录

1. 泛型概述

1.1 生活中的例子

1.2 泛型的引入

2. 使用泛型举例

2.1 集合中使用泛型

2.1.1 举例

2.1.2 练习

2.2 比较器中使用泛型

2.2.1 举例

2.2.2 练习


1. 泛型概述

1.1 生活中的例子

  • 举例1:中药店,每个抽屉外面贴着标签

  • 举例2:超市购物架上很多瓶子,每个瓶子装的是什么,有标签

  • 举例3:家庭厨房中:

Java中的泛型,就类似于上述场景中的标签

1.2 泛型的引入

        在Java中,我们在声明方法时,当在完成方法功能时如果有未知的数据需要参与,这些未知的数据需要在调用方法时才能确定,那么我们把这样的数据通过形参表示。在方法体中,用这个形参名来代表那个未知的数据,而调用者在调用时,对应的传入实参就可以了。

        受以上启发,JDK1.5设计了泛型的概念。泛型即为“类型参数”,这个类型参数在声明它的类、接口或方法中,代表未知的某种通用类型。

举例1:

        集合类在设计阶段/声明阶段不能确定这个容器到底实际存的是什么类型的对象,所以在JDK5.0之前只能把元素类型设计为Object,JDK5.0时Java引入了“参数化类型(Parameterized type)”的概念,允许我们在创建集合时指定集合元素的类型。比如List<String>,这表明该List只能保存字符串类型的对象。

        使用集合存储数据时,除了元素的类型不确定,其他部分是确定的(例如关于这个元素如何保存,如何管理等)。

举例2:

  java.lang.Comparable接口和java.util.Comparator接口,是用于比较对象大小的接口。这两个接口只是限定了当一个对象大于另一个对象时返回正整数,小于返回负整数,等于返回0,但是并不确定是什么类型的对象比较大小。JDK5.0之前只能用Object类型表示,使用时既麻烦又不安全,因此 JDK5.0 给它们增加了泛型。

其中<T>就是类型参数,即泛型。

所谓泛型,就是允许在定义类、接口时通过一个标识表示类中某个属性的类型或者是某个方法的返回值或参数的类型。这个类型参数将在使用时(例如,继承或实现这个接口、创建对象或调用方法时)确定(即传入实际的类型参数,也称为类型实参)。

2. 使用泛型举例

        自从JDK5.0引入泛型的概念之后,对之前核心类库中的API做了很大的修改,例如:JDK5.0改写了集合框架中的全部接口和类、java.lang.Comparable接口、java.util.Comparator接口、Class类等。为这些接口、类增加了泛型支持,从而可以在声明变量、创建对象时传入类型实参。

2.1 集合中使用泛型

2.1.1 举例

集合中没有使用泛型时:

集合中使用泛型时:

Java泛型可以保证如果程序在编译时没有发出警告,运行时就不会产生ClassCastException异常。即,把不安全的因素在编译期间就排除了,而不是运行期;既然通过了编译,那么类型一定是符合要求的,就避免了类型转换。

同时,代码更加简洁、健壮。

把一个集合中的内容限制为一个特定的数据类型,这就是generic背后的核心思想。

举例:

//泛型在List中的使用
@Test
public void test1(){//举例:将学生成绩保存在ArrayList中//标准写法://ArrayList<Integer> list = new ArrayList<Integer>();//jdk7的新特性:类型推断ArrayList<Integer> list = new ArrayList<>();list.add(56); //自动装箱list.add(76);list.add(88);list.add(89);//当添加非Integer类型数据时,编译不通过//list.add("Tom");//编译报错Iterator<Integer> iterator = list.iterator();while(iterator.hasNext()){//不需要强转,直接可以获取添加时的元素的数据类型Integer score = iterator.next();System.out.println(score);}
}

举例:

//泛型在Map中的使用
@Test
public void test2(){HashMap<String,Integer> map = new HashMap<>();map.put("Tom",67);map.put("Jim",56);map.put("Rose",88);//编译不通过//        map.put(67,"Jack");//遍历key集Set<String> keySet = map.keySet();for(String str:keySet){System.out.println(str);}//遍历value集Collection<Integer> values = map.values();Iterator<Integer> iterator = values.iterator();while(iterator.hasNext()){Integer value = iterator.next();System.out.println(value);}//遍历entry集Set<Map.Entry<String, Integer>> entrySet = map.entrySet();Iterator<Map.Entry<String, Integer>> iterator1 = entrySet.iterator();while(iterator1.hasNext()){Map.Entry<String, Integer> entry = iterator1.next();String key = entry.getKey();Integer value = entry.getValue();System.out.println(key + ":" + value);}}
2.1.2 练习

练习1:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
import java.util.function.Predicate;public class TestNumber {public static void main(String[] args) {ArrayList<Integer> coll = new ArrayList<Integer>();Random random = new Random();for (int i = 1; i <= 5 ; i++) {coll.add(random.nextInt(100));}System.out.println("coll中5个随机数是:");for (Integer integer : coll) {System.out.println(integer);}//方式1:使用集合的removeIf方法删除偶数coll.removeIf(new Predicate<Integer>() {@Overridepublic boolean test(Integer integer) {return integer % 2 == 0;}});//方式2:调用Iterator接口的remove()方法//Iterator<Integer> iterator1 = coll.iterator();//while(coll.hasNext()){//    Integer i = coll.next();//   if(i % 2 == 0){//       coll.remove();//    }//}System.out.println("coll中删除偶数后:");Iterator<Integer> iterator = coll.iterator();while(iterator.hasNext()){Integer number = iterator.next();System.out.println(number);}}
}

2.2 比较器中使用泛型

2.2.1 举例
public class Circle{private double radius;public Circle(double radius) {super();this.radius = radius;}public double getRadius() {return radius;}public void setRadius(double radius) {this.radius = radius;}@Overridepublic String toString() {return "Circle [radius=" + radius + "]";}}

使用泛型之前:

import java.util.Comparator;class CircleComparator implements Comparator{@Overridepublic int compare(Object o1, Object o2) {//强制类型转换Circle c1 = (Circle) o1;Circle c2 = (Circle) o2;return Double.compare(c1.getRadius(), c2.getRadius());}
}
//测试:
public class TestNoGeneric {public static void main(String[] args) {CircleComparator com = new CircleComparator();System.out.println(com.compare(new Circle(1), new Circle(2)));System.out.println(com.compare("圆1", "圆2"));//运行时异常:ClassCastException}
}

使用泛型之后:

import java.util.Comparator;class CircleComparator1 implements Comparator<Circle> {@Overridepublic int compare(Circle o1, Circle o2) {//不再需要强制类型转换,代码更简洁return Double.compare(o1.getRadius(), o2.getRadius());}
}//测试类
public class TestHasGeneric {public static void main(String[] args) {CircleComparator1 com = new CircleComparator1();System.out.println(com.compare(new Circle(1), new Circle(2)));//System.out.println(com.compare("圆1", "圆2"));//编译错误,因为"圆1", "圆2"不是Circle类型,是String类型,编译器提前报错,//而不是冒着风险在运行时再报错。}
}
2.2.2 练习

MyDate.jave

package exer1;/*** ClassName:IntelliJ IDEA* Description:*      2、MyDate类包含:*      private成员变量year,month,day,并为每一个属性定义getter、setter方法* @Author zyjstart* @Create:2024/10/5 16:02*/
public class MyDate {private int year;private int month;private int day;public MyDate() {}public MyDate(int year, int month, int day) {this.year = year;this.month = month;this.day = day;}public int getYear() {return year;}public void setYear(int year) {this.year = year;}public int getMonth() {return month;}public void setMonth(int month) {this.month = month;}public int getDay() {return day;}public void setDay(int day) {this.day = day;}@Overridepublic String toString() {return year + "年" + month + "月" + day + "日";}
}

Employee.java

package exer1;/*** ClassName:IntelliJ IDEA* Description:*      1、定义一个Employee类:*      该类包含:private成员变量name,age,birthday,其中birthday为MyDate类的对象:*      并为每一个属性定义getter,setter方法*      并重写toString方法输出name,age,birthday* @Author zyjstart* @Create:2024/10/5 16:00*/
public class Employee implements Comparable<Employee>{private String name;private int age;private MyDate birthday;public Employee() {}public Employee(String name, int age, MyDate birthday) {this.name = name;this.age = age;this.birthday = birthday;}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;}public MyDate getBirthday() {return birthday;}public void setBirthday(MyDate birthday) {this.birthday = birthday;}@Overridepublic String toString() {return "Employee{" +"name='" + name + '\'' +", age=" + age +", birthday=" + birthday +'}';}//按照name从高到低排序@Overridepublic int compareTo(Employee o) {return this.name.compareTo(o.name);}
}

EmployeeTest.java

package exer1;import org.junit.Test;import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;/*** ClassName:IntelliJ IDEA* Description:*      3、创建该类的5个对象,并把这些对象放入TreeSet集合中(TreeSet 需使用泛型来定义)**      4、分别按以下两种方式对集合中的元素进行排序,并遍历输出:*          1)、使Employee实现Comparable接口,并按name排序*          2)、创建TreeSet时传入Comparator对象,按生日日期的先后排序* @Author zyjstart* @Create:2024/10/5 16:05*/
public class EmployeeTest {//1)、使Employee实现Comparable接口,并按name排序@Testpublic void test1(){TreeSet<Employee> set = new TreeSet<>();Employee e1 = new Employee("Hanmeimei",18,new MyDate(1998,12,16));Employee e2 = new Employee("Gaoqiqi",25,new MyDate(2002,11,19));Employee e3 = new Employee("Daleiju",34,new MyDate(1944,6,24));Employee e4 = new Employee("Zixianxina",17,new MyDate(1999,8,27));Employee e5 = new Employee("Yinana",37,new MyDate(2011,1,31));set.add(e1);set.add(e2);set.add(e3);set.add(e4);set.add(e5);//遍历Iterator<Employee> iterator = set.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}}//2)、创建TreeSet时传入Comparator对象,按生日日期的先后排序@Testpublic void test2() {Comparator<Employee> comparator = new Comparator<Employee>() {@Overridepublic int compare(Employee o1, Employee o2) {// 先比较年int yearDistince = o1.getBirthday().getYear() - o2.getBirthday().getYear();if (yearDistince != 0){ // 如果年份不相等,返回结果,相等,则判断月份return yearDistince;}// 比较月int monthDistince = o1.getBirthday().getMonth() - o2.getBirthday().getMonth();if (monthDistince != 0){return monthDistince;}return o1.getBirthday().getDay() - o2.getBirthday().getDay();}};TreeSet<Employee> set = new TreeSet<>(comparator);Employee e1 = new Employee("Hanmeimei",18,new MyDate(1999,12,16));Employee e2 = new Employee("Gaoqiqi",25,new MyDate(2002,11,19));Employee e3 = new Employee("Daleiju",34,new MyDate(1944,6,24));Employee e4 = new Employee("Zixianxina",17,new MyDate(1999,8,27));Employee e5 = new Employee("Yinana",37,new MyDate(2011,1,31));set.add(e1);set.add(e2);set.add(e3);set.add(e4);set.add(e5);//遍历Iterator<Employee> iterator = set.iterator();while (iterator.hasNext()){System.out.println(iterator.next());}}
}

在EmployeeTest.java中有两个测试方法,分别对应两个目标要求

test1按姓名排序,输出

test2按出生年月排序,输出

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/54640.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

图示详解OpenEuler下 DNS安装、配置与测试

前言 DNS配置内容、步骤、参数较多&#xff0c;初学者很难短时间掌握&#xff0c;另外&#xff0c;理解DNS工作原理也有一定的难度&#xff0c;一次配置成功的概率不大&#xff0c;因此&#xff0c;建议在配置DNS之前&#xff0c;先读一下之前笔者的博文《详解DNS工作原理及实…

(20)MATLAB使用卡方(chi-square)分布生成Nakagami-m分布

文章目录 前言一、使用卡方分布函数生成Nakagami分布随机变量二、MATLAB仿真1.仿真代码2.运行结果 前言 Nakagami分布随机变量的生成&#xff0c;可以使用gamma分布实现&#xff0c;也可以使用卡方&#xff08;chi-square&#xff09;分布随机变量生成。使用伽马&#xff08;g…

120页满分PPT | 企业级业务架构和IT架构规划方案

方案内容综述 方案涵盖了从战略分析到具体实施路径的内容。提出了IT架构规划的工作思路&#xff0c;包括项目启动、部门访谈、资料收集、内部数据库搜索与先进实践研究等步骤&#xff0c;旨在通过这些步骤完成现状及差距分析&#xff0c;并基于此设计未来的应用架构、数据架构…

算法:724.寻找数组的中心下标

题目 链接&#xff1a;leetcode链接 思路分析&#xff08;前缀和&#xff09; 根据题意&#xff0c;我们可以将数组看成三个部分 [left] [mid] [right] 我们只需要[left]区间内的元素和等于[right]区间的元素和即可&#xff0c;此时mid就是中心下标 那么我们可以借助前缀和思…

鸿蒙开发之ArkUI 界面篇 二十 position绝对定位及层级zIndex

position控制组件的位置&#xff0c;可以实现层叠效果&#xff0c;Android中的FramLayout,通常用在左上角有些图标之类&#xff0c;绝对定位后的组件不占用自身原有位置,每个子组件都有这个属性&#xff0c;只是不用这个属性的时候不起作用&#xff0c;.zIndex()属性要和positi…

微服务——分布式事务

目录 分布式事务 1.1分布式事务的特性 1.2分布式事务应用背景 ​编辑 1.3.认识Seata 1.4部署TC服务 1.4.1.准备数据库表 1.4.2.准备配置文件 1.4.3.Docker部署 1.5.微服务集成Seata 1.5.1.引入依赖 1.5.2.改造配置 1.5.3.添加数据库表 ​编辑1.6.XA模式 1.6.1.两…

聊聊Mysql的MVCC

1 什么是MVCC&#xff1f; MVCC&#xff0c;是Multiversion Concurrency Control的缩写&#xff0c;翻译过来是多版本并发控制&#xff0c;和数据库锁一样&#xff0c;他也是一种并发控制的解决方案。 我们知道&#xff0c;在数据库中&#xff0c;对数据的操作主要有2种&#…

【数据结构 | PTA】表

文章目录 7-1 重排链表7-2 链表去重7-3 两个有序链表序列的合并7-4 两个有序链表序列的交集 7-1 重排链表 输入格式&#xff1a; 每个输入包含1个测试用例。每个测试用例第1行给出第1个结点的地址和结点总个数&#xff0c;即正整数N (≤105)。结点的地址是5位非负整数&#xff…

K8s持久化存储PV和PVC(通俗易懂)

一、PV和PVC的引入 Volume 提供了非常好的数据持久化方案,不过在可管理性上还有不足。 拿前面 AWS EBS 的例子来说,要使用 Volume,Pod 必须事先知道如下信息: 当前 Volume 来自 AWS EBS。EBS Volume 已经提前创建,并且知道确切的 volume-id。Pod 通常是由应用的开发人员…

Linux安装配置Jupyter Lab并开机自启

文章目录 1、安装配置jupyter lab首先需要使用pip3安装&#xff1a;生成配置文件和密码&#xff1a; 2、设置开机自启首先通过which jupyter查询到可执行文件路径&#xff1a;设置自启服务&#xff1a; 1、安装配置jupyter lab 首先需要使用pip3安装&#xff1a; pip3 instal…

细说机器学习和深度学习

背景 平常业务开发中每天都要接触到机器学习和深度学习的概念&#xff0c;在听了很多大佬的普及后&#xff0c;发现甚是有趣。于是小编想着着手开始学习这部分的内容。 那废话不多说&#xff0c;就从最基础的机器学习和神经网络开始~ 一、机器学习基础 1、机器学习是什么&a…

2024 uniapp入门教程 01:含有vue3基础 我的第一个uniapp页面

uni-app官网uni-app,uniCloud,serverless,快速体验,看视频&#xff0c;10分钟了解uni-app,为什么要选择uni-app&#xff1f;,功能框架图,一套代码&#xff0c;运行到多个平台https://uniapp.dcloud.net.cn/ 准备工作&#xff1a;HBuilder X 软件 HBuilder X 官网下载&#xf…

职场上的人情世故,你知多少?这五点一定要了解

职场是一个由人组成的复杂社交网络&#xff0c;人情世故在其中起着至关重要的作用。良好的人际关系可以帮助我们更好地融入团队&#xff0c;提升工作效率&#xff0c;甚至影响职业发展。在职场中&#xff0c;我们需要了解一些关键要素&#xff0c;以更好地处理人际关系&#xf…

泛微流程隐藏按钮

隐藏右键菜单的按钮 控制台输入 mobx.toJS(WfForm.getGlobalStore().rightMenu.rightMenus) 获取相对应 type在js中进行隐藏 ecodeSDK.overwritePropsFnQueueMapSet(WeaRightMenu,{ //复写组件名隐藏菜单fn:(newProps)>{ //newProps代表组件参数newProps.datas newProps.…

Hierarchical Cross-Modal Agent for Robotics Vision-and-Language Navigation

题目&#xff1a;用于视觉语言导航的层次化跨模态智能体 摘要 1. 问题背景和现有方法 VLN任务&#xff1a;这是一种复杂的任务&#xff0c;要求智能体基于视觉输入和自然语言指令进行导航。 现有方法的局限性&#xff1a;之前的工作大多将这个问题表示为离散的导航图&#x…

MySQL基础教程(一):连接数据库和使用表

这个专栏用来讲解 MySQL 数据的基本语法和用法。本教程的目的是方便查询 MySQL 的用法&#xff0c;因此对于原理的讲解会偏少一些&#xff0c;但特点就是会有很多实验操作图。 本专栏使用的源材料是《MySQL必知必会》这本书的源代码。 文章目录 1. 连接 MySQL 数据库2. 创建数…

【物流配送中心选址问题】基于改进粒子群算法

课题名称&#xff1a; 基于改进粒子群算法的物流配送中心选址问题 改进方向&#xff1a;动态惯性权重优化粒子群算法 代码获取方式&#xff1a; 模型描述&#xff1a; 待补充 Matlab仿真结果&#xff1a; 1. 模型优化后的仿真结果 2. 初始解对应的物流配送路径图 3. 粒子…

Tianrui Green Shield

Tianrui Green Shield&#xff0c;即天锐绿盾&#xff0c;是一款专注于企业数据防泄密的软件系统。以下是对天锐绿盾的详细介绍&#xff1a; 一、基本信息 产品名称&#xff1a;天锐绿盾&#xff08;又名绿盾信息安全管理软件&#xff09;公司官网&#xff1a;www.drhchina.co…

VMware中Ubuntu系统Docker正常运行但网络不通(已解决)

问题描述&#xff1a;在VMware中的Ubuntu系统下部署了Docker&#xff0c;当在docker容器中运行Eureka微服务时&#xff0c;发现Eureka启动正常&#xff0c;但无法通过网页访问该容器中Eureka。 解决办法如下&#xff1a; 1、创建桥接网络&#xff1a;test-net sudo docker n…

2024年最强网络安全学习路线,详细到直接上清华的教材!

关键词&#xff1a;网络安全入门、渗透测试学习、零基础学安全、网络安全学习路线 首先咱们聊聊&#xff0c;学习网络安全方向通常会有哪些问题前排提示&#xff1a;文末有CSDN官方认证Python入门资料包 &#xff01; 1、打基础时间太长 学基础花费很长时间&#xff0c;光语…