J2SE中的内外比较器的想法

java中的内外比较器的想法

JavaSE中的比较器在javaSE中有很重要的地位。对于类中的成员变量的比较都是很有帮助的。在javaSE中类中的成员变量中有String类型,有int类型,有枚举型等等,那么这些成员变量如果有多个对象调用他们的话,怎么去比较他们的大小呢?

首先,第一步:

因为成员变量在类中一般是私有化的,所以我们首先由geter和seter来构建访问私有化的成员变量。在此之前要对成员变量利用构造函数的形式进行初始化。(如下图):


 

生成getter和setter访问方法(如下图):

 

第二步:创建内部比较器:

内部比较器的几个注意事项:

1.它在一个类的内部;

2.比较之前本类先实现(Implements)Comparable<本类名>接口,外部比较器实现的是Comperator接口(不加本类名而且重新写一个类进行实现)

3.如果是本类的对象的本类引用则在进行比较的时候不需要进行向上类型强转,

如果是父类的引用指向本类的对象,比较的时候就需要向上类型强转。

4.在比较器的参数类型中可以是Object。

5.内部比较器的参数列表中只有一个类型和一个形式参数。

6.如果比较String类型的成员变量用,格式:this.成员变量名.ComparTo(形式参数.成员变量)将结果复制给一个int类型的变量,并将这个变量返回。(在API中String的比较已经由底层进行实现,所以这个地方直接拿来就用就好了)

7.如果是int类型的成员变量进行比较的时候,直接进行减法即可,如:int result=this.age-形式参数.age,将这个结果result返回。如果age比较不出来的时候呢,就要考虑到用if条件语句进行判断其他的成员变量,这时if条件语句中的判断值,设置为==0;再判断不出来继续用其他的成员变量进行判断,继续用if条件语句。因为当进行Compar进行比较的时候返回1时,则表示前面的值大于后面的,如果是0值,则代表这两个值相等,如果是-1值的时候则表示前面的值小于后面的值。

8.在实现接口后,一般编辑器会提示你进行:添加未实现的方法。如果没有实现会造成报错。

(如下图):

 

此时一个内部比较器就创建好了。

那么怎么调用这个内部比较器呢?

1.在集合框架内:在主函数内也就是测试页里面,创建collection的子接口(List,set等)的父类和其引用指向子接口的子类所创建的对象,这个地方会有泛型存在,一般设置为有成员变量和成员方法的类名。如下图


2.直接用collections.sort(子接口的引用);就好了。

下一步就是打印了。这是集合中的如果的非集合呢?

我们先来看一下:

我们在一个类中定义两个变量,一个变量是name,一个变量是age这两个变量的数据类型分别是String和int类型的,并且把这两个属性私有化。那么我们怎么来设置和修改他们的内容呢?

第一步:

1.初始化成员变量,用类中的创建构造器的方法。

2.设置这两个成员变量的getter和setter的访问方法;

3.重写toString方法。

(如下图):

 

第二步:

1.现在我们就要开始进行创建内部比较器了,在创建内部比较器的时候我们首先要让这个类实现(implement)比较器的接口(Comparable)泛型为:本类名;

2.在实现Comparable接口以后编辑器会自动的提示你进行:添加未实现的方法,这是将鼠标点到红色下波浪线处进行生成。在上图中已经实现了Comparable接口这里就不再附图了。

第三步:

在实现Comparable以后呢,我们就开始进行重写CompareTo的方法了,

在上一步的第2小步骤中我们已经实现了编辑器为我们自动生成的CompareTo方法了,现在我们就根据我们自己的需求来重写这个方法。

这里一定要说明的是name是String类型的我们在比较的时候就不能进行减法的赋值运算,所以是直接用int result=this.name-o.name;这里要说明的是在内部比较器中我们的参数列表中的参数类型是:本类名;形式参是:o,下一步就开始比较age了,在比较age的时候要注意,age也可以先比较,不管是先比较还是后比较我们一定要加一个if条件语句的判断。将if条件语句的内容设置为if(result==0),这样做的目的是,if条件语句进行判断的成员变量,这时if条件语句中的判断值,设置为==0;再判断不出来继续用其他的成员变量进行判断,继续用if条件语句。因为当进行Compar进行比较的时候返回1时,则表示前面的值大于后面的,如果是0值,则代表这两个值相等,如果是-1值的时候则表示前面的值小于后面的值。最后记得返回;如下图:

 

接下来我们来测试一下。定义主函数,创建Comper类的对象(两个),调用setter方法设置name。直接进行ComparTo的比较方法对两个对象进行比较,再将比较后的结果打印出来。在结果打印出来以后我们会发现一个现象,输出的值要么很大要么很小要么等于0。产生这种这种现象的原因是。我们输入的字符在底层算法里映射的都是Unicode码表。在Unicode码表中所有的字符都有自己所对应的数字,在字符比较的时候其实是底层的数字在进行减法运算。前者见后者为正数,则前者大;相等则两个字符相等;负数则前者小后者大。如下图:

 

下面我们正式开始我们的内部比较器的使用了,在使用内部比较器的时候我先要建立多个对象,这时候要向里面进行传参,传参有两种办法,一是修改构造方法的参数列表,使得参数列表和对象的列表一致。二是:不修改构造方法,使用对象继续调用setter方法进行传参。然后再建立以类名为类型的数组,指定其长度要和对象的元素的个数相吻合。千万不要角标越界。把每一个对象一一存储到数组里面来,用Arrays.toString方法进行数组打印。如下图:

 

结果图:

 

上图中的排序结果是按照age进行排序的。因为我把内部比较器中的name进行了注释,这样为了凸显排序的结果。

内部比较器大约就是这些内容下面我们看外部比较器的创建和使用。

外部比较器:

外部比较器顾名思义,就是外面设定的比较器,既然是外面设置的比较器,那我们得用一个全新的类来实现外部比较器。

说明外部比较器和内部比较器没有冲突,写到一起也是可以的。

第一步:

1.创建一个全新的类;

2.让这个类实现Comperator接口,并将Comperator的java.util包导入进来,添加未实现的方法。注意事项:在Copmerator这个接口会有一个泛型类,这个泛型类就是我们成员变量所在的类。

3.修改比较器中的参数列表。注意这里的参数列表中的两个参数类型和成员变量所在的类的名称相同,形式参数不用去管他。

4.类型转换:将两个形式参数(对象)强制转换为和两个参数类型一致的类型,并赋值给左边的参数类型的引用。

5.设定接受结果的int类型的result,将两个形式参数指向同一个的以int类型的成员变量,具体操作是形式参数调用这个属性的getter获取方法,并让这个参数做减法运算(注意:两个对象(也叫参数)对应两个不同的引用)。记得返回result。以上操作如下图:

 

上面的步骤结束以后就可以开始下面的步骤了:

第二步:

1.在主函数中建立外部比较器所在全新类的对象。

2.继续用API中java.util.Arrsys中的sort方法,但这时再用时就和内部比较器不同了,内部比较器可以直接将数组名传入Arrays.sort()中,外部比较器是不能的。外部比较器sort里面得先传入数组名+外部比较器全新类的对象的引用才可以。为什么呢?下面说:

 

这是因为在内存中的问题:

在内存中有栈内存和堆内存之分。首先看存取速度仅次于寄存器的栈内存:

栈内存有几个特性:

1.存取速度快(仅次于寄存器)

2.先进后出的原则(原因是:栈内存中有一个指针,可以理解为指针初始的时候在栈的最低端指向数据入口处,当一个数据进来以后指针就往上移一位,这时入口处就会有第二个指针在等待第二个数据进来,当进来的一个数据和栈内存出现同一类型的不同引用有相同的值时栈中的指针会指向同一个值,也就是说同类型的数据进来以后展栈会在自己的内训中先进行寻找自己有没有这个值有的话就和这个进来的同一类型不同引用指向同一个值,所以当我们需要改变这两个同一类型不同的引用的数据时,这种改变对另外的一个数据没任何影响,而如果我们改变这个值时栈会在自己的空间里先寻找有没有我们改变的这个值,有就指向,没有就重新创建。)

3.里面存储的都是代码块中的局部变量或者是对象的引用。

4.当变量和引用结束自己玩的作用域的时候,栈内存会立即清除数据。但此时堆内存中的数组和对象不会立即清除这要等堆内存在一个不确定的时间来自动清除,即便在代码中加入System.cg()效果也是一样的。

堆内存:

1.用来存放数组和对象的地方。

2.里面的数据在结束以后不会立即清除,而是会留在里面在一个不确定的时间等待系统自动清除,这个也就是Java程序耗费内存的原因。

3.内一个数组和对象都有自己在堆中的存储地址,这个地址是以一个十六进制的数进行表示的。当栈中的引用指向某一地址值时,堆中的对象就把地址值给了栈中的引用,此时栈中的引用具有对象的一切内容。

方法区:

1.用来放静态变量和静态代码块的;

2.各个线程共享的内存区域,它用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。

3.用来配合栈内存进行代码的调用的。三者的关系如下图:

 

4.明白了这个就好解释外部比较器sort里面得先传入数组名+外部比较器全新类的对象的引用才可以了。

外部比较器的所在的类和存入对象的数组这两个new出来的都在堆中,而这两个对象所拥有的类的信息都在方法区内,当这两个对象的引用得到对象的一切以后,comp先通过方法区找到自己的类信息要得到一个要排序的数组,得出一个数组以后,把这个数组间接地传给ComparE(其实先直接的先传给方法区,再由方法区直接给ComparE)再由ComparE在方法区中找到自己的类信息把comp给他的数据加载到自己程序中,比较完了以后把比较完的结果给sort方法,再由sort方法加载到这自己的程序里进行,最后sort把这个结果返回给comp,这时就得到了一个排好的数组了。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值