比较器和浅谈深浅拷贝

news2024/11/17 8:45:46

比较器和浅谈深浅拷贝


文章目录

  • 比较器和浅谈深浅拷贝
  • 前言
  • 一.比较器
    • 方法一
    • 方法二
  • 二.深浅拷贝
    • 2.1 浅拷贝
    • 2.2 深拷贝
    • 2.3 总结


前言

我们学习完接口以后,我在这里会介绍一个比较器的接口,至于他是来干嘛的,比较器顾名思义就是来比较的,其他的倒是没什么讲究的。


一.比较器

我们还是用具体的例子来解释这个东西具体的用法。我下面会给出一个student的类,main方法中我会给出student的数组,存入数据,然后我需要你对这个数组进行排序并输出。代码如下:

public class Student {
    public String name;
    public int age;
    public int score;

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

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

public class Test
{
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0] = new Student("zhagnsan",10,19);
        students[1] = new Student("abc",8,78);
        students[2] = new Student("lisi",15,57);
        Arrays.sort(students);

    }

当然我们了解过数组,自然而然就想到数组的sort方法,但实际上是不可行的,因为student是一个对象,不是一个单纯的数据,因此你这样做的话,会出现一个错误。如下:
在这里插入图片描述


当然我们还是要想办法,java当然也给我们提供了方法去比较,有以下俩种方法。

方法一

分俩步走
1.学生类去实现Comparable接口。
2.重写接口的compareTo方法。这个方法就是写比较方法的。

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

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

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

    @Override
    public int compareTo(Student s) {
        return s.age - this.age;
    }
}
public class Test
{
    public static void main(String[] args) {
        Student[] students = new Student[3];
        students[0] = new Student("zhagnsan",10,19);
        students[1] = new Student("abc",8,78);
        students[2] = new Student("lisi",15,57);
        Arrays.sort(students);
        System.out.println(Arrays.toString(students));

    }

}


结果:
在这里插入图片描述

当然肯定有人说,重写compareTo方法遇见了String怎么办,字符串貌似没法用相减的方法,不必担心,string类已经重写了compareto的方法,我们可以直接用,代码如下:

  public int compareTo(Student o) {
        if (this.name.compareTo(o.name)>0){
            return 1;
        }else if (this.name.compareTo(o.name)<0){
            return -1;
        }
        return 0;
    }

string类重写的方法如下:

 public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

说了这么久compare这个接口,大家应该对这个接口熟悉,但是我要说的是这个东西我觉得不够好,因为我们每一次的比较都写死了,如果是比较年龄,我们就只能比较年龄,你如果想比较其他的东西,就必须要修改student类的方法,这基本上的是不好的,有没有解决方案呢?当然是有的,接下来的方法二就是我们要说的。


方法二

我们会用到一个Comparator的接口,具体的用法,入下:
1.生成一个类,比如说我们按照年龄比较,我们就定义一个年龄类,然后实现Comparator接口
2.重写compare的方法
代码如下:

public class Student {
    public String name;
    public int age;
    public int score;

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

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


}
//比较名字的
class NameComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.name.compareTo(o2.name);
    }
}
//按照分数比较的
class ScoreComparator implements Comparator<Student> {
    @Override
    public int compare(Student o1, Student o2) {
        return o1.score - o2.score;
    }
}
//按照年龄比较的
class AgeComparator implements Comparator<Student> {

    @Override
    public int compare(Student o1, Student o2) {
        return o1.age - o2.age;
    }
}

测试方法:

public class Test
{

        Student[] students = new Student[3];
        students[0] = new Student("zhagnsan",10,19);
        students[1] = new Student("abc",8,78);
        students[2] = new Student("lisi",15,57);

        //比较器
        AgeComparator ageComparator = new AgeComparator();

        ScoreComparator scoreComparator = new ScoreComparator();

        NameComparator nameComparator = new NameComparator();
		//第二个参数就是传入比较器,然后就按照比较器的方式进行比较。
        Arrays.sort(students,ageComparator);

        System.out.println(Arrays.toString(students));

    }

}

在这里插入图片描述

总结:
这种方法的好处更灵活了,我们想按照哪种方式去比较,我们直接传入相应的比较器就可以了,就不需要去类体中修改方法了,增加代码的复用性。


二.深浅拷贝

在进入这个拷贝的讲解之前呢?先介绍一个接口,这个接口就是Cloneable,为啥要说这个呢?那是因为我们要对一个对象进行拷贝的时候,我们必须去实现这个cloneable接口,才能进行拷贝,我们也可以看一下这个cloneable接口的内容
在这里插入图片描述
这里面是什么都没有的,简单来说,我们去实现这个接口,就是为这个类打上了标记,说明这个类是可以被拷贝的。


一般来说我们拷贝的步骤如下:
1.我们必须给类实现一个Cloneable接口
2.重写父类object的clone的方法

2.1 浅拷贝

浅拷贝对于基本数据类型就是直接进行值传递,在内存的另一个空间内存放,修改这个值不会影响到拷贝源的值
浅拷贝对于引用数据类型就是进行的是地址传递,并没有对该对象重新开辟一个内存空间进行存放,所以对于引用数据类型的浅拷贝就相当于两个引用指向了同一个内存地址,那么就显而易见了修改拷贝后的值就会影响到拷贝源的值。 简单点来说就是浅拷贝就是怎么变都会影响另一个变量的值。

我这里用一个学生类来解释这个浅拷贝的例子,附代码

//学生类
public class Student implements Cloneable {
    public String name;
    public Money m=new Money();

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }
}
//money类
public class Money implements Cloneable {
    public double money=12.25;

}
//测试类
public class Test {
    public static void main(String[] args) throws CloneNotSupportedException {
      Student student1 = new Student();
        Student student2 = (Student)student1.clone();
        System.out.println(student1.m.money);
        System.out.println(student2.m.money);
        student2.m.money = 99;                  
		System.out.println(student1.m.money);   
		System.out.println(student2.m.money);   
    }
}

运行结果:
在这里插入图片描述

为啥会出现这样的结果呢?我画个图大家理解一下。
在这里插入图片描述
为啥会出现这样的一种现象呢?原因就是我们在克隆时重写clone方法的时候,你仔细看。
在这里插入图片描述
我们仅仅只是克隆了整个对象,并没有对money这个类进行复制,所以money的引用自始至终都指向了同一个对象。


2.2 深拷贝

我们怎么才能改变这种现状呢?那必定要在重写clone的方法上做手脚,我的代码修改如下:

public class Student implements Cloneable {
    public String name;
    public Money m=new Money();

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

    @Override
    protected Object clone() throws CloneNotSupportedException {
        //下面这一行代码只是克隆了,父类的值
        Student student=(Student) super.clone();
        //这行代码要克隆student 里面money的对象
        student.m=(Money) this.m.clone();
        //克隆完成之后,我们返回student对象
        return student;
//        return super.clone();
    }
}
public class Money implements Cloneable {
    public double money=12.25;
    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

然后我们再去运行程序后:
在这里插入图片描述
具体上面的代码修改后,发生了什么事情呢,我再画个图,大家再去深刻的理解一下:
在这里插入图片描述

2.3 总结

1.我们进行拷贝之前,必须让类实现Cloneable
2.实现接口后,必须重写类的clone方法。
3.重写方法的方式,不同,造就的结果不同,就导致了,浅拷贝和深拷贝

这次到这里,我们就结束了,哈哈,是不是弄清楚了呢?嘻嘻。

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

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

相关文章

【安卓学习之常见问题】百度地图卫星地图精度不够

█ 【安卓学习之常见问题】百度地图卫星地图精度不够 █ 系列文章目录 提示&#xff1a;这里是收集了和文件分享有关的文章 【安卓学习之常见问题】android路径及文件问题 【安卓学习之常见问题】文件分享–文件不存在 【安卓学习之常见问题】自定义组件-刷新后跳到第一行 【…

修复 IDEA 使用 Gradle 构建出错时的乱码问题(maven项目转Gradle后乱码,并报“错误,找不到符号”)

在迁移一个基于 Maven 构建项目到基于 Gradle 进行构建, 迁移的过程中发现编译失败了, IDEA 的 Gradle build output 面板出现了许多方块型的乱码. 这样子&#xff1a; 解决步骤1&#xff1a; Step 1: 点击 IDEA 顶部菜单栏中的 HelpStep 2: 点击 Edit Custom VM OptionsStep…

天权信安catf1ag网络安全联合公开赛-AGCTFS战队 wp

文章目录webPOPEzloginFileuploadHistoryMISC简单隐写十位马CryptoEasyrsa疑惑ReverseCheckinPwnCheckinAngrweb POP 脚本 <?php class catf1ag1{ public $hzy; public $arr; public function __construct(){$this->hzy new catf1ag2;$this->arr [&apos;pp…

数据库实验二:安全性语言实验

实验二 安全性语言实验 实验 2.1 自主存取控制实验 1.实验目的 掌握自主存取控制权限的定义和维护方法。 2.实验内容和要求 定义用户、角色&#xff0c;分配权限给用户、角色&#xff0c;回收权限&#xff0c;以相应的用户名登录数据库验证权限分配是否正确。选择一个应用…

【GRU回归预测】基于matlab鲸鱼算法优化门控循环单元WOA-GRU神经网络回归预测(多输入单输出)【含Matlab源码 2285期】

⛄一、CNN-GRU数据预测 1 理论基础 1.1 CNN算法 负荷序列数据为一维数据&#xff0c;用一维卷积核对数据进行卷积处理&#xff0c;以获取数据的特征。 现设定卷积核的维度为3&#xff0c;移动步长为1&#xff0c;对输入数据进行卷积&#xff0c;以获得特征图图谱&#xff0c;即…

postgresql_internals-14 学习笔记(四)TOAST 超尺寸字段存储技术

TOAST之前一直没太弄懂&#xff0c;这一节单独拆出来学习。 一、 引入原因 pg中的每个行只能存在一个page里&#xff0c;不能跨page存储。因此对于一些非常长的行&#xff0c;就需要使用到 TOAST&#xff08;The OverSized Attribute Storage Technique&#xff0c;超尺寸字段存…

import sklearn出现报错,如何正确安装sklearn

目录 一&#xff1a;前言 二&#xff1a;解决方法 三&#xff1a;测试是否成功安装 一&#xff1a;前言 博主最早只使用下面安装命令&#xff0c;安装sklearn pip3 install sklearn -i https://pypi.mirrors.ustc.edu.cn/simple/ 但在pycharm编辑器&#xff0c;导入sklearn模…

更合理的 BBR

BBR 倾向于排空队列&#xff0c;甚至用特殊的 ProbeRTT 状态来排空自己产生的队列以测量 RTT&#xff0c;但这并不现实。一言以蔽之&#xff0c;BBR 无法实时跟踪现状&#xff0c;只靠拢理想。 若因背景流量造成 buffer 抖动&#xff0c;BBR 完全无法应对&#xff0c;其运行状…

手撕B树 | 二三查找树,B+树B*树你都会了吗? | 超详细的数据结构保姆级别实现

说在前面 今天给大家带来B树系列数据结构的讲解&#xff01; 博主为了这篇博客&#xff0c;做了很多准备&#xff0c;试了很多画图软件&#xff0c;就是为了让大家看得明白&#xff01;希望大家不要吝啬一键三连啊&#xff01;&#xff01; 前言 那么这里博主先安利一下一些…

C语言百日刷题第十六天

前言 今天是刷题第16天&#xff0c;放弃不难&#xff0c;但坚持一定很酷~ 五套C语言验报告题 C语言百日刷题第十六天前言试验报告&#xff08;一&#xff09;试验报告&#xff08;二&#xff09;分析功能编写程序试验报告&#xff08;三&#xff09;分析功能编写程序试验报…

自定义图表--随意拖拽拉伸功能的实现

随意拖拽、拉伸元素的功能是现在大热的自定义图表的重要组成功能,本文以最简单的视角搞懂随意拖拽、拉伸元素功能,完成这个功能需要先了解原生 drag && vue-ruler-tool && @smallwei/avue demo在线体验地址:zhao-wenchao110.gitee.io/customdrag 一、了解H…

高并发内存池

"花,就在火海里摇曳开着。" 一、技术介绍 (1)什么是池化技术&#xff1f; 池 是在计算机技术中经常使用的一种设计模式&#xff0c;其内涵在于&#xff1a;将程序中需要经常使用的核心资源先申请出来&#xff0c;放到一个池内,由程序自己管理。这样可以提高资源的使…

【单调栈】接雨水

文章目录双指针动态规划单调栈双指针 每一列雨水的高度&#xff0c;取决于该列 min(左侧最高的柱子高度&#xff0c;右侧最高的柱子高度) - 当前柱子高度 class Solution { public:int trap(vector<int>& height) {int n height.size();int ans 0;for(int i 1; …

ZY_BMP280大气压模块的使用和程序

在搞设计时&#xff0c;用到了大气压模块BMP280&#xff0c;这玩意也不难&#xff0c;主要是淘宝店老板特别der一问三不知&#xff0c;真服了&#xff0c;而且资料里面没有给例程&#xff0c;只有51的例程&#xff0c;利用IIC通信&#xff0c;而且给的例程里面&#xff0c;乱七…

数据库实验五:数据库设计实验

实验五 数据库设计实验 1.实验目的 ​ 掌握数据库设计基本方法及数据库设计工具。 2.实验内容和要求 ​ 掌握数据库设计基本步骤&#xff0c;包括数据库概念结构设计、逻辑结构设计&#xff0c;物理结构设计&#xff0c;数据库模式SQL语句生成。能够使用数据库设计工具进行…

ctf笔记:编码

常见编码 博客链接&#xff1a;https://www.blog.23day.site/articles/76 计算机中的数据都是按字节存储。一个字节(Byte)由8个二进制位组成(bit)。&#xff08;组成范围是0~255(28))一个字节一共可以用来表示256种不同的状态&#xff0c;每一个状态对应一个符号&#xff0c;就…

推荐系统学习笔记-隐语义模型

由来 该算法最早在文本挖掘领域被提出&#xff0c;用于找到文本的隐含语义。 核心思想是通过隐含特征(latent factor) 联系用户兴趣和物品。 参数 f&#xff1a;隐向量维度&#xff0c;决定隐向量表达能力强弱 n&#xff1a;用户数 m&#xff1a;物品数 求解方法&#xff1a;…

ADI Blackfin DSP处理器-BF533的开发详解57:DSP控制ADV7180采集图像到LCD显示(含源码)

硬件准备 ADSP-EDU-BF533&#xff1a;BF533开发板 AD-HP530ICE&#xff1a;ADI DSP仿真器 软件准备 Visual DSP软件 硬件链接 代码实现功能 代码实现了采集一帧 720625 尺寸的 P 制 CVBS 信号源&#xff0c;以 YUYV422 的数据格式保存&#xff0c;通过 MDMA 将奇偶场数据交…

【轻松掌握C语言】文件操作

目录 一、为什么使用文件&#xff1f; 二、什么是文件&#xff1f; 1、程序文件 2、数据文件 3、文件名 三、文件操作 1、文件指针 2、文件打开与关闭 . 3、文件的顺序读写 4、文件的随机读写 5、文本文件和二进制文件 6、文件读取结束判定 四、文件缓冲区 一、…

C++ Reference: Standard C++ Library reference: Containers: map: map: rbegin

C官网参考链接&#xff1a;https://cplusplus.com/reference/map/map/rbegin/ 公有成员函数 <map> std::map::rbegin C98 reverse_iterator rbegin(); const_reverse_iterator rbegin() const; C11 reverse_iterator rbegin() noexcept; const_reverse_iterator rbegin(…