Java 比较器 和 包装类

发布时间:2026/11/6 4:50:39
Java 比较器 和 包装类

Java比较器

背景:

在Java中经常会涉及到多个对象的排序问题,那么就涉及到对象之间的比较

  • Java中的对象, 正常情况下, 只能进行比较

    ==比较对象地址值,是否相同

    !=比较对象地址值,是否相同,取反~

    不能使用 > 或 < 的

  • 但是在开发场景中,我们需要对多个对象进行排序,言外之意,就需要比较对象的大小

  • 以 JD 商城举例场景: 查询商品可以对商品进行:价格 销量 评论 购买数...排序

    实际上这里面是查询每一个商品都是一个个商品对象

    对象属性:商品名 评论数 价格 销量 店铺 图片地址...

  • 根据用户点击,从数据库中查询到一个商品对象/数组进行排序,返回数据给前端进行排序展示~

    当然, 一个功能可以有很多种实现方式, 也有直接在数据库中根据传过来的类型, 动态sql 直接在数据库中查询返回排好序的数据!

Java实现对象排序:

  • 这里主要介绍,以Java方式实现的对象排序…

  • Java实现对象排序的方式有两种:

    自然排序:Java.lang.Comparable

    定制排序:Java.util.Comparator

自然排序:Java.lang.Comparable看牌啊爆

Java Comparable接口强行对实现它的每个类的对象进行整体排序这种排序被称为:自然排序

  • Java类, 实现implementsComparable接口,重写compareTo(Object o); 的方法;

  • 两个对象即通过compareTo(Object o)方法的返回值来比较大小

    如果当前对象 this 大于形参对象 o ,则返回正整数 1

    如果当前对象 this 小于形参对象 o ,则返回负整数 -1

    如果当前对象 this 等于形参对象 o ,则返回零 0

  • 实现Comparable接口的类的对象数组(和有序集合)可以通过 Arrays.sort(和 Collections.sort )进行自动排序

  • Comparable的典型实现

    **String、包装类等实现了Comparable接口,重写了compareTo(obj)方法 **默认都是从小到大排序

    String:按照字符串中字符的Unicode值进行比较

    Character:按照字符的Unicode值来进行比较

    数值类型对应的包装类以及BigInteger、BigDecimal:按照它们对应的数值大小进行比较

    Boolean:true 对应的包装类实例大于 false 对应的包装类实例true.compareTo( false); —返回—> 1

    Date、Time等:后面的日期时间比前面的日期时间大2021.compareTo( 2020 ); —返回—> 1

String、包装类实现 Comparable接口Demo

ComparaTest.Java

packagecom.wsm.comparatest;importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.Arrays;importjava.util.Date;publicclassComparaTest{//Java String、包装类等实现了Comparable接口publicstaticvoidmain(String[]args){//String 类实现了, Comparable 接口!并且实现Comparable 接口!可以直接使用: Arrays.sort Collections.sort 进行排序!String[]arr=newString[]{"AA","cc","ac","dd","aa","FF","ff"};Arrays.sort(arr);System.out.println(Arrays.toString(arr));//[AA, FF, aa, ac, cc, dd, ff]//Char 的包装类, Character 实现Comparable 接口!按照字符的Unicode值来进行比较;chara='a';charb='b';System.out.println("a="+(int)a+"\n"+"b="+(int)b);CharacteraC='a';CharacterbC='b';System.out.println(aC.compareTo(bC));// a<b = -1//Boolean 包装类实现了, Comparable 接口!Booleanok=true;Booleanno=false;System.out.println("Boolean类型: true > false:"+ok.compareTo(no));//int 等基本数据类型的包装类实现了, Comparable 接口!Integerone=1;Integertwo=2;System.out.println("基本数据类型包装类比较,直接根据值进行比较:"+one.compareTo(two));//Data 日期类型实现, Comparable 接口!SimpleDateFormatsdf=newSimpleDateFormat("yyyy");DatethisYear=null;DatelastYear=null;try{thisYear=sdf.parse("2021");lastYear=sdf.parse("2020");}catch(ParseExceptione){e.printStackTrace();}System.out.println("日期类型比较,最近的日期最大:"+thisYear.compareTo(lastYear));}}

自然排序Demo

Commodity.Java

定义一个商品类:

/** * 创建一个商品类; */publicclassCommodityimplementsComparable{//商品名privateStringname;//商品价格privateintprice;//商品销量privateintsales;//点赞数privateintlike;//...更多不举例子了.../** 实现implements Comparable接口,重写 compareTo(Object o)类 *//** 指明商品比较大小的方式:按照价格从低到高排序,再按照产品名称从高到低排序 */@OverridepublicintcompareTo(Objecto){// instanceof: 判断传入参数类型是否是 商品类型,进入if 进行比较!if(oinstanceofCommodity){// Object 类型强制转换,父类向下转换!Commodityo1=(Commodity)o;if(this.price>o1.price){//如果当前对象 大于> 传入对象返回 1;return1;}elseif(this.price<o1.price){//如果当前对象 小于< 传入对象返回 -1;return-1;}else{//相等则在进行判断...移此类推返回 0;//return 0; //相等,应该返回0 但我们还需要进行判断商品名称从高到底~//因为商品名称是 String类型, String 本身已经实现了 comparable 所以👇👇return-this.name.compareTo(o1.name);//默认都是从小到大排序,加个 - 号取反~}}thrownewRuntimeException("传入的数据类型不一致!");}//有参构造publicCommodity(Stringname,intprice,intsales,intlike){this.name=name;this.price=price;this.sales=sales;this.like=like;}//重写toString 不然打印地址值!@OverridepublicStringtoString(){return"Commodity{"+"name='"+name+'\''+", price="+price+", sales="+sales+", like="+like+'}';}//省略 get/set..}

上面的 compareTo(Object o) 方法中,如果只是根据对象的一个属性进行排序…可以直接使用一个基本数据类型包装类,进行 campareTo()

CommodityTest.Java

importjava.util.Arrays;/** 测试类 */publicclassCommodityTest{publicstaticvoidmain(String[]args){Commodity[]commodities=newCommodity[5];commodities[0]=newCommodity("a",1,1,1);commodities[1]=newCommodity("b",1,1,1);commodities[2]=newCommodity("c",2,1,1);commodities[3]=newCommodity("d",3,1,1);commodities[4]=newCommodity("a",4,1,1);System.out.println("第一次遍历数组:");for(Commoditycommodity:commodities){System.out.println(commodity);}//调用方法,给数组排序...Arrays.sort(commodities);System.out.println("Arrays.sort排序后遍历数组:");//name 从大到小~System.out.println("a="+(int)'a');System.out.println("b="+(int)'b');for(Commoditycommodity:commodities){System.out.println(commodity);}}}

定制排序:Java.Util.Comparator看牌啊特

当元素没有实现 Comparable接口, 而不方便修改代码

或者实现了 Comparable 接口, 但其排序的操作,并不符合当前操作

  • String 默认从大小排,而我想要从小到大排序……而可以考虑 Comparator 类型对象来排序

Compartor

  • Comparator接口中只有两个抽象方法

    int compare(Object o1, Object o2);

    boolean equals(Object obj);接口实现类默认继承了Object类的equals方法, 间接实现了方法。

    因此只需实现int compare(Object o1, Object o2);

  • Arrays.sort 和 Collections.sort存在多态方法

    Arrays.sort(T[],Comparator<? super T>);

    Collections.sort(T[],Comparator<? super T>);

实现:

  • 可以将Comparator接口实现类传递给 sort(T[],Comparator<? super T>) 方法,从而允许在排序顺序上实现精确控制。

  • Comparator当作内部类,直接传递给方法,内部类中重写int compare(Object o1, Object o2)方法比较o1和o2的大小

定制排序Demo

ComparatorTest.Java

importjava.util.Arrays;importjava.util.Comparator;/** ComparatorTest测试Demo */publicclassComparatorTest{//直接拿String 类进行操作, String类本身实现了 comparable接口;publicstaticvoidmain(String[]args){/** 混乱的String[] */String[]arr=newString[]{"CC","MM","KK","AA","DD","GG","JJ","EE"};//默认从小到大排序System.out.println("默认从小到大排序");Arrays.sort(arr);System.out.println(Arrays.toString(arr));System.out.println("按照字符串从大到小的顺序排列");//按照字符串从大到小的顺序排列, new Comparator(){ ... } 内部类操作;Arrays.sort(arr,newComparator(){//重写compare(Object o1, Object o2) 方法@Overridepublicintcompare(Objecto1,Objecto2){//类型判断全栈类型转换if(o1instanceofString&&o2instanceofString){Strings1=(String)o1;Strings2=(String)o2;return-s1.compareTo(s2);}thrownewRuntimeException("输入的数据类型不一致");}});System.out.println(Arrays.toString(arr));}}

两者的区别

  • 只要实现Comparable 接口的对象直接就成为一个可以比较的对象,但是需要修改源代码

  • 用Comparator 的好处是不需要修改源代码

    而是在待比较对象的类的外部实现一个比较器

    当某个自定义的对象需要作比较的时候,把待比较对象和比较器一起传递过去就可以实现排序功能。

  • 像String类、包装类等JDK内置类实现了Comparable接口默认是升序排序

    如果要降序排序或指定其他排序规则只能使用Comparator接口。

扩展:

instanceof

  • instanceof是 Java 的一个二元操作符,类似于 ==,>,< 等操作符
  • instanceof 是 Java 的保留关键字它的作用是测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型

Java 遵循 – 得正~

System.out.println("Java遵循‘负负得正’ 数学公式:"+(-(-1)));

Java包装类

什么是包装类型

Java 设计当初就提供了 8种基本数据类型

  • int byte short longfloat doublebooleanchar

及对应的包装类

  • Integer Byte Short LongFloat DoubleBooleanCharacter位于Java.lang包下

基本数据类型 和 包装类基本一致, 首字母大写类名首字母大写, 本就是规范😀就是 int 和 char 有点不一样…基本使用都一致,这里就以 int 举例:

包装类应用场景

  • 集合类泛型只能是包装类

    List<int> list1 = new ArrayList<>();编译报错

    List<Integer> list2 = new ArrayList<>();正常

  • 包含了每种基本类型的相关属性,如最大值,最小值,所占位数等常用方法()…

  • 作为基本数据类型, 有时候我们想要进行一些对象的操作,基本数据类型无法直接完成!

    在Java中,一切皆对象,但八大基本类型却不是对象

基本数据类型-----包装类-----String 的转换

  • 包装类通过 Integer.toString() 将整型转换为字符串Object 的方法~

  • 包装类通过 Integer.parseInt(“123”) 将字符串转换为int类型

  • 包装类通过valueOf()方法, 将字符/数值转换换成包装类对象.虽然和基本数据类型存在自动装箱/拆箱~

自动装箱拆箱

Java5.0 之后新增的两个功能:自动装箱自动拆箱

  • 自动装箱:

    装箱就是将: 基本数据类型 ——转换—— 为对象类型Integer a = 100;

  • 自动拆箱:

    拆箱就是将:对象类型 ——转换为—— 基本数据类型int b = a;

PackClass.Java

/** 包装类Demo */publicclassPackClass{publicstaticvoidmain(String[]args){//Integer 是int 类型的包装类, 内置了大量的方法操作System.out.println("int 的最大值:"+Integer.MAX_VALUE);System.out.println("int 的最小值:"+Integer.MIN_VALUE);//...//构造方法:// new Integer(int); new Integer(String);// 将int 和 String 转换成Integer对象; (JDK8已过时 ~)//创建一个Integer//1.构造函数Integerc1=newInteger("540");//2.自动装箱Integerc2=540;//3.使用提供的 valueof( int/String );// 构造函数方式已经被淘汰了... 使用String 注意String必须满足是数字符, 不可以是 abc...Integerc3=Integer.valueOf("540");//因为 Integer 是对象了,每一个对象都会又一个对应栈地址, == 比较地址所以返回falseSystem.out.println(c1==c2);System.out.println(c1==c3);System.out.println(c2==c3);//即使这样也不例外!Integerc22=540;System.out.println(c2==c22);//但 Integer 和 int 进行比较是直接比较值, 底层会进行 "自动拆箱"intc33=540;System.out.println(c3==c33);//Integer 和 int 可以进行,数值计算/比较~System.out.println(c3+c33);//自动装箱 拆箱Integerw=123;System.out.println("自动装箱:"+w);intw1=newInteger("123");System.out.println("自动拆箱:"+w1);System.out.println("自动装箱拆箱就是: 基本数据类型 和 引用类型(包装类), 之间的相互转换~");//String 包装类 基本数据类型 相互转换/** 基本类型转换为字符串(3) */intc=10;//使用包装类的 toString() 方法Stringstr1=Integer.toString(c);//使用String类的 valueOf() 方法Stringstr2=String.valueOf(c);//用一个空字符串加上基本类型,得到的就是基本类型数据对应的字符串Stringstr3=c+"";/** 字符串转换为基本类型 */Stringstr="8";//调用包装类的parseXxx()静态方法intd=Integer.parseInt(str);//调用包装类的valueOf()方法转换为基本类型的包装类,会自动拆箱inte=Integer.valueOf(str);/** 字符串转换为包装类 *///通过构造函数 字符参数//通过valueof("");Integerinteger=Integer.valueOf("8");System.out.println(integer);}}

总结:

Java八大基本数据类型都有对应的包装类,使基本数据类型也具有对象的操作…

  • 并且内部定义了一些方法,方便使用…
  • 结合:自动装箱/拆箱基本数据类型,使用起来更加的心用手~

Integer与int的区别

int是java提供的8种原始数据类型之一

  • Java为每个原始类型提供了封装类,Integer是java为int提供的封装类

  • int的默认值为0

  • Integer的默认值为null

    **即Integer可以区分出未赋值和值为0的区别 **int则无法表达出未赋值的情况

    判断一个人考试,0分和缺考则只能使用Integer

  • 在JSP开发中,Integer的默认为null

    所以用el表达式在文本框中显示时,值为空白字符串

    int默认的默认值为0,所以用el表达式在文本框中显示时,结果为0int不适合作为web层的表单数据的类型

  • Integer提供了多个与整数相关的操作方法

    将一个字符串转换成整数,Integer中还定义了表示整数的最大值和最小值的常量

本文由博客一文多发平台 OpenWrite 发布!