Java初识泛型 | 如何通过泛型类/泛型方法实现求数组元素最大值?

news2025/1/8 5:43:23

目录

一、引言

二、编程分析

1、泛型类实现

思路

代码

2、泛型方法实现

思路

代码 

三、拓展:数组排序(以冒泡排序为例)

1、int类型 原代码

2、泛型类

3、泛型方法


一、引言

给定一个整型数组,求数组中所有元素的最大值

该题同样是编程入门的基础题。关键在于拓展:能不能通过程序,实现给定的任意类型的数组,都能求出数组中所有元素的最大值?

这里我们先给出整型数组求最大值的代码,作为基础:

public class Util {
    public int findMaxInt(int[] array) {
        int max = array[0];
        for (int i = 0; i < array.length; i++) {
            if(max < array[i]) {
                max = array[i];
            }
        }
        return max;
    }
}

 调用并运行:

public class Test {
    public static void main(String[] args) {
        int[] array = {1,0,9,4,5};
        System.out.println("max is " + util.findMaxInt(array));
    }
}

 接下来我们来分析,如果通过泛型类或泛型方法使程序能够适用于任意一个数据类型。


二、编程分析

1、泛型类实现

解题之前,我们首先要了解泛型、泛型上界、泛型方法的概念。对于这些概念有所遗忘的同学,可以阅读文章:🔗Java初识泛型 | 如何通过泛型类/泛型方法获取任意类型的三个数的最大值?的知识解析部分熟悉一下。

这里,我们直接讲解思路,不再进行基础知识的铺垫。

思路

按照泛型的思路,我们试着将原来的类改成泛型类。用占位符E代替原代码中所有的int。但仅仅更改这些,最后会发现编译器在比较的位置报错了:

是什么原因导致编译失败呢? 

原因:max和array[i]都是E类型也就是引用类型的变量,两个引用变量之间不能用大于小于号进行大小比较。可行的方法应当是调用比较对象的compareTo()方法。但是,compareTo()方法是不能直接调用的,它要求调用的对象的类型必须实现过Comparable接口。

如图 尝试直接调用compareTo()方法失败

换句话说,它对类型E有约束,这个约束就是: 必须实现过Comparable接口。因此,这里要用到类型的上界的知识,来进行约束。

public class Util<E extends Comparable<E>> {
    ...
}

<E extends Comparable<E>> 的含义为:传入的E类型必须是实现了Comparable接口的。如果传入的类型没有实现过Comparable接口,那么编译会报错。

此时,我们可以成功地调用compareTo()方法了:

此时调用成功

 整合后,便能得出完整的代码了。

代码

泛型类: 

public class Util<E extends Comparable<E>> {
    public E findMax(E[] array) {
        E max = array[0];
        for (int i = 0; i < array.length; i++) {
            if(max.compareTo(array[i]) < 0) {
                max = array[i];
            }
        }
        return max;
    }
}

调用:

Integer

public class Test {
    public static void main(String[] args) {
        Util<Integer> util = new Util<>();
        Integer[] array = {1,0,9,4,5};
        System.out.println("max is " + util.findMax(array));
    }
}

Double(只需更改main中的数据类型即可,Util类不用变动)

public class Test {
    public static void main(String[] args) {
        Util<Double> util = new Util<>();
        Double[] array = {13.6,100.5,0.0,-3.1,5.8};
        System.out.println("max is " + util.findMax(array));
    }
}

String 

public class Test {
    public static void main(String[] args) {
        Util<String> util = new Util<>();
        String[] array = {"China","America","Australia","Ireland"};
        System.out.println("max is " + util.findMax(array));
    }
}

自定义的类型Tmp,已手动实现了Comparable<Tmp>接口

//Tmp.java

public class Tmp implements Comparable<Tmp>{
    public int parameter1;
    public String parameter2;

    public Tmp(int parameter1, String parameter2) {
        this.parameter1 = parameter1;
        this.parameter2 = parameter2;
    }

    @Override
    public int compareTo(Tmp o) {
        //以parameter2为标准来比较Tmp
        //parameter2是String类,比较可以直接调用String类的compareTo方法
        return this.parameter2.compareTo(o.parameter2);
    }

    @Override
    public String toString() {
        return "Tmp{" +
                "parameter1=" + parameter1 +
                ", parameter2='" + parameter2 + '\'' +
                '}';
    }
}
//Test.java

public class Test {
    public static void main(String[] args) {
        Util<Tmp> util = new Util<>();
        Tmp tmp1 = new Tmp(10,"substantial");
        Tmp tmp2 = new Tmp(20,"circumspect");
        Tmp tmp3 = new Tmp(5,"coby");
        Tmp[] array = {tmp1,tmp2,tmp3};
        System.out.println("max is " + util.findMax(array));
    }
}


2、泛型方法实现

思路

如果用泛型类实现,则每次使用前还需要创建类对象。能不能把这一个步骤省去呢?答案是可以的,我们可以通过静态泛型方法来完成。

按照泛型方法的语法,我们对原代码稍作修改:

public class Util {
    public static  <E>  E findMax(E[] array) {
        ...
    }
}

此时的Util类已经不再是泛型类了,而是一个普通类。通过在修饰符后添加 static <E> 将普通方法改为了静态泛型方法。但此时还不够完善,同样的,我们需要把类型参数E实现了Comparable接口这一约束体现出来。只需要把<E>改为 <E extends Comparable<E>> 即可。

代码 

public class Util {
    public static  <E extends Comparable<E>>  E findMax(E[] array) {
        E max = array[0];
        for (int i = 0; i < array.length; i++) {
            if(max.compareTo(array[i]) < 0) {
                max = array[i];
            }
        }
        return max;
    }
}

此时,测试时的代码也更加简略了:

public class Test {
    public static void main(String[] args) {
        Tmp tmp1 = new Tmp(10,"substantial");
        Tmp tmp2 = new Tmp(20,"circumspect");
        Tmp tmp3 = new Tmp(5,"coby");
        Tmp[] array = {tmp1,tmp2,tmp3};
        System.out.println("max is " + Util.findMax(array));
    }
}

依旧能够正确运行


三、拓展:数组排序(以冒泡排序为例)

1、int类型 原代码

//Tmp.java

public class Tmp{
    public static void bubbleSort(int[] array){
        for (int i = 0; i < array.length-1; i++) {
            boolean flag = false;
            for (int j = 0; j < array.length-1-i; j++) {
                if(array[j] > array[j+1]) {
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                    flag = true;
                }
            }
            if(!flag) {
                break;
            }
        }
    }
}
//Test.java

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        int[] array = {0,3,1,8,9,6,4,5,2};
        Tmp.bubbleSort(array);
        System.out.println(Arrays.toString(array));
    }
}

2、泛型类

//Util.java

public class Util<E extends Comparable<E>> {
    public void bubbleSort(E[] array){
        for (int i = 0; i < array.length-1; i++) {
            boolean flag = false;
            for (int j = 0; j < array.length-1-i; j++) {
                if(array[j].compareTo(array[j+1]) > 0) {
                    E tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                    flag = true;
                }
            }
            if(!flag) {
                break;
            }
        }
    }
}
//Test.java

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        Util<Integer> util = new Util<>();
        Integer[] array = {10,8,-33,7,21,78};
        util.bubbleSort(array);
        System.out.println(Arrays.toString(array));
    }
}

3、泛型方法

//Util.java

public class Util {
    public static <E extends Comparable<E>> void bubbleSort(E[] array){
        for (int i = 0; i < array.length-1; i++) {
            boolean flag = false;
            for (int j = 0; j < array.length-1-i; j++) {
                if(array[j].compareTo(array[j+1]) > 0) {
                    E tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                    flag = true;
                }
            }
            if(!flag) {
                break;
            }
        }
    }
}

//Test.java

import java.util.Arrays;

public class Test {
    public static void main(String[] args) {
        Integer[] array = {10,8,-33,7,21,78};
        Util.bubbleSort(array);
        System.out.println(Arrays.toString(array));
    }
}

拓展阅读: 🔗Java初识泛型 | 如何通过泛型类/泛型方法获取任意类型的三个数的最大值?

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

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

相关文章

JVM知识体系学习三:class文件初始化过程、硬件层数据一致性(硬件层)、缓存行、指令乱序执行问题、如何保证不乱序(volatile等)

文章目录前言一、class文件初始化过程1、概述2、初始化过程-案例1a、代码T001_ClassLoadingProcedure 类加载过程b、解析3、初始化过程-案例2a、代码b、解析二、单例模式-双重检查三、硬件层数据一致性1、硬件层的并发优化基础知识b、Intel 的缓存一致性协议&#xff1a;MESI四…

Vivado综合设置之-keep_equivalent_registers

-keep_equivalent_registers即保留等效寄存器&#xff0c;所谓等效寄存器是指共享输入端口&#xff08;输入时钟端口clk和输入数据端口rst&#xff09;的寄存器。 勾选它时&#xff0c;意味着Vivado不会对等效寄存器进行优化&#xff1b; 不勾选它时&#xff08;默认情况&…

eclipse安装UML插件

安装AmaterasUML AmaterasUML 是一个用于 Eclipse 的轻量级 UML 和 ER 图编辑器。 将AmaterasUML的3个jar包拷到Eclpise的plugins文件下&#xff1a; 重启eclipse 在新建菜单中可以发现已经出现了UML文件选项 安装GEF插件&#xff08;Eclipse2018-12 以后无需安装&#xf…

②电子产品拆解分析-电动牙刷

②电子产品拆解分析-电动牙刷一、功能介绍二、电路分析以及器件作用1、振动电机开关控制电路2、锂电池供电与充电电路三、本产品的优缺点1、优点&#xff1a;2、缺点&#xff1a;一、功能介绍 ①5档工作模式&#xff1b;②2分钟倒计时停止工作&#xff1b;③工作续航一个星期以…

【MySQL】详解索引操作

索引什么是索引&#xff1f;索引的优势和劣势索引类型按数据结构分类按物理存储分类按字段特性分类主键索引唯一索引普通索引全文索引前缀索引按字段个数分类索引操作创建索引创建主键索引唯一索引的创建普通索引的创建全文索引的创建explain工具查询索引删除索引索引最好设置为…

SQL 注入学习路线

学习路线&#xff08;大致&#xff09; HTML > SQL > Python > SQL 注入&#xff08;使用 sqli-labs 靶场来学习 SQL 注入&#xff09; HTML 视频 【前端开发入门教程&#xff0c;web前端零基础html5 css3前端项目视频教程】 要求 使用该视频进行 HTML 基础部分…

Python之字符串的特点

1.布尔值 Python2中没有布尔值&#xff0c;直接用数字0表示Flase&#xff0c;用数字1表示True。Python3中&#xff0c;把True和False定义成了关键字&#xff0c;但他们的本质还是1和0&#xff0c;甚至可以和数字相加。 >>> a True >>> b 3 >>> …

[多图,秒懂]如何训练一个“万亿大模型”?

1. 背景近几年&#xff0c;随着“大模型”概念的提出&#xff0c;深度学习模型越来越大&#xff0c;如何训练这些大模型成为一个亟待解决的工程问题。最初的视觉模型只有几百兆的参数量&#xff0c;而现在的语言模型中&#xff0c;动则百亿&#xff0c;千亿的参数量&#xff0c…

[golang工作日记] for range 踩坑

1、for range指针赋值 Ops的数据保存在两个表中&#xff0c;一个是ops_tab&#xff0c;另一个是staff_tab&#xff0c;其中ops_tab的staff_id是staff_tab的外键&#xff0c;两个表都有staff_id字段。 type OpsDetail struct {OpsId stringStaffId stringOps *model.Ops…

Node.js安装配置

目录1. 下载node2. 安装3. 检查是否安装成功4. 配置缓存路径5. 实现一个demo1. 下载node 官方地址https://nodejs.org/en/下载长期支持版本 2. 安装 一路next node一起安装npm 这个地方不要勾选 安装成功 3. 检查是否安装成功 cmd运行下面命令 # 查看node的版本 node -v # …

【博客571】“时序敏感应用“ 如何prometheus自定义上报时间戳

“时序敏感应用” 如何prometheus自定义上报时间戳 1、场景 在物理网络监控中&#xff0c;对于流量趋势是极其敏感的&#xff0c;物理网络监控流量的点通常是秒级别甚至毫秒级别&#xff0c;此时这些时许点通过各种上报上传到监控系统中&#xff0c;由于网络波动&#xff0c;可…

Kubernetes v1.24.2高可用部署

sskubeasz 1、Kubeasy简介 kubeasz 致力于提供快速部署高可用k8s集群的工具, 同时也努力成为k8s实践、使用的参考书&#xff1b;基于二进制方式部署和利用ansible-playbook实现自动化&#xff1b;既提供一键安装脚本, 也可以根据安装指南分步执行安装各个组件。 kubeasz 从每…

【lc刷题 day12】堆/栈/队列

BM42 用两个栈实现队列 easy import java.util.Stack;public class Solution {Stack<Integer> stack1 new Stack<Integer>();Stack<Integer> stack2 new Stack<Integer>();public void push(int node) {stack1.push(node);}public int pop() {if(st…

随便聊聊浪潮开务数据库

今天这个话题挺随意&#xff0c;我们来聊聊浪潮开务数据库&#xff0c;原因主要是我的微信朋友圈被这个数据库刷屏了。当然我对这款号称多模数据库的非开源数据库也很感兴趣&#xff0c;也有很多疑问&#xff0c;希望各位专家能帮忙答疑解惑&#xff0c;揭开这款即将发布的 Kai…

机器学习--多层感知机、卷积神经网络、循环神经网络

目录 一、多层感知机 二、卷积神经网络 三、循环神经网络 总结 一、多层感知机 手工提取特征&#xff08;用人的知识进行&#xff09; --> 神经网络来提取特征。 神经网络&#xff08;可能更懂机器学习&#xff09;来提取 可能对后面的线性或softmax回归可能会更好一…

【UE4 第一人称射击游戏】23-添加子弹伤害

上一篇&#xff1a;https://blog.csdn.net/ChaoChao66666/article/details/128589063?spm1001.2014.3001.5501本篇效果&#xff1a;步骤&#xff1a;创建一个蓝图类&#xff08;父类为Character&#xff09;&#xff0c;命名为“SimpleAI”双击打开“SimpleAI”&#xff0c;点…

非对称加密实战(一):JDK生成keystore获取公钥私钥及代码验证【附源码】

目录使用说明非对称加密生成keystore文件公钥私钥互相解密获取fd-alias.keystore中的公钥私钥使用生成公钥私钥进行解密源码地址使用说明 非对称加密 非对称加密算法主要有&#xff1a;RSA、Elgamal、背包算法、Rabin、D-H、ECC&#xff08;椭圆曲线加密算法&#xff09;。下…

TensorRT学习笔记--基于FCN-ResNet101推理引擎实现语义分割

目录 前言 1--Pytorch模型转换为Onnx模型 2--Onnx模型可视化及测试 2-1--可视化Onnx模型 2-2--测试Onnx模型 3--Onnx模型转换为Tensor RT推理模型 4--基于Tensor RT使用推理引擎实现语义分割 前言 基于Tensor RT的模型转换流程&#xff1a;Pytorch → Onnx → Tensor RT…

通用vue组件化首页

一、首先先建立文件main.vue,构建主体 1.选择合适的模板element-plus,直接复制 2.编写相应的样式 <template><div class"main"><el-container class"main-content"><el-aside> aside </el-aside><el-container class&q…

2022年中职组网络安全竞赛D模块竞赛漏洞报告单总结

Windows加固 后门用户 漏洞发现过程 打开cmd使用net user 看到”hacker”用户,疑似存在后门用户 使用hacker/123456成功登录目标服务器,证明存在后门用户 漏洞加固过程 删除后门用户