Java比較器
背景:
在Java中經常會涉及到多個對象的排序問題,那麼就涉及到對象之間的比較
- Java中的對象, 正常情況下, 隻能進行比較
比較對象位址值,是否相同==
!=
比較對象位址值,是否相同,取反~
不能使用 > 或 < 的
- 但是在開發場景中,我們需要對多個對象進行排序,言外之意,就需要比較對象的大小
Java 比較器 和 包裝類Java比較器Java包裝類 - 以 JD 商城舉例場景: 查詢商品可以對商品進行:
實際上這裡面是查詢每一個商品都是一個個價格 銷量 評論 購買數...排序
對象屬性:商品對象
商品名 評論數 價格 銷量 店鋪 圖檔位址...
- 根據使用者點選,從資料庫中查詢到一個
進行排序,傳回資料給前端進行排序展示~商品對象/數組
當然, 一個功能可以有很多種實作方式, 也有直接在資料庫中根據傳過來的類型, 動态sql 直接在資料庫中查詢傳回排好序的資料!
Java實作對象排序:
- 這裡主要介紹,以Java方式實作的對象排序...
-
Java實作對象排序的方式有兩種:
自然排序:Java.lang.Comparable
定制排序:Java.util.Comparator
自然排序:Java.lang.Comparable 看牌啊爆
看牌啊爆
Java Comparable接口強行對實作它的每個類的對象進行整體排序
這種排序被稱為:自然排序
- Java類, 實作
Comparable接口,重寫implements
compareTo(Object o); 的方法;
- 兩個對象即通過
compareTo(Object o)
方法的傳回值來比較大小
如果目前對象 this 大于形參對象 o ,則傳回正整數 1
如果目前對象 this 小于形參對象 o ,則傳回負整數 -1
如果目前對象 this 等于形參對象 o ,則傳回零 0
- 實作
接口的類的對象數組(和有序集合)可以通過 Arrays.sort(和 Collections.sort )進行自動排序Comparable
-
Comparable的典型實作
*String、包裝類等實作了Comparable接口,重寫了compareTo(obj)方法 *
預設都是從小到大排序
String:按照字元串中字元的Unicode值進行比較
Character:按照字元的Unicode值來進行比較
數值類型對應的包裝類以及BigInteger、BigDecimal:按照它們對應的數值大小進行比較
Boolean:true 對應的包裝類執行個體大于 false 對應的包裝類執行個體
Date、Time等:後面的日期時間比前面的日期時間大true.compareTo( false); —傳回—> 1
2021.compareTo( 2020 ); —傳回—> 1
String、包裝類實作 Comparable接口 Demo
Demo
ComparaTest.Java
package com.wsm.comparatest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
public class ComparaTest {
//Java String、包裝類等實作了Comparable接口
public static void main(String[] args) {
//String 類實作了, Comparable 接口!并且實作Comparable 接口!可以直接使用: Arrays.sort Collections.sort 進行排序!
String[] arr = new String[]{"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值來進行比較;
char a = 'a';
char b = 'b';
System.out.println("a="+(int)a+"\n"+"b="+(int)b);
Character aC = 'a';
Character bC = 'b';
System.out.println(aC.compareTo(bC)); // a<b = -1
//Boolean 包裝類實作了, Comparable 接口!
Boolean ok = true;
Boolean no = false;
System.out.println("Boolean類型: true > false:"+ok.compareTo(no));
//int 等基本資料類型的包裝類實作了, Comparable 接口!
Integer one = 1;
Integer two = 2;
System.out.println("基本資料類型包裝類比較,直接根據值進行比較:"+one.compareTo(two));
//Data 日期類型實作, Comparable 接口!
SimpleDateFormat sdf = new SimpleDateFormat("yyyy");
Date thisYear = null;
Date lastYear = null;
try {
thisYear = sdf.parse("2021");
lastYear = sdf.parse("2020");
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("日期類型比較,最近的日期最大:"+thisYear.compareTo(lastYear));
}
}
自然排序Demo
自然排序Demo
Commodity.Java
定義一個商品類:
/**
* 建立一個商品類;
*/
public class Commodity implements Comparable {
//商品名
private String name;
//商品價格
private int price;
//商品銷量
private int sales;
//點贊數
private int like;
//...更多不舉例子了...
/** 實作implements Comparable接口,重寫 compareTo(Object o)類 */
/** 指明商品比較大小的方式:按照價格從低到高排序,再按照産品名稱從高到低排序 */
@Override
public int compareTo(Object o) {
// instanceof: 判斷傳入參數類型是否是 商品類型,進入if 進行比較!
if(o instanceof Commodity){
// Object 類型強制轉換,父類向下轉換!
Commodity o1 = (Commodity) o;
if(this.price > o1.price){ //如果目前對象 大于> 傳入對象傳回 1;
return 1;
}else if(this.price < o1.price){ //如果目前對象 小于< 傳入對象傳回 -1;
return -1;
}else { //相等則在進行判斷...移此類推傳回 0;
//return 0; //相等,應該傳回0 但我們還需要進行判斷商品名稱從高到底~
//因為商品名稱是 String類型, String 本身已經實作了 comparable 是以👇👇
return -this.name.compareTo(o1.name);//預設都是從小到大排序,加個 - 号取反~
}
}
throw new RuntimeException("傳入的資料類型不一緻!");
}
//有參構造
public Commodity(String name, int price, int sales, int like) {
this.name = name;
this.price = price;
this.sales = sales;
this.like = like;
}
//重寫toString 不然列印位址值!
@Override
public String toString() {
return "Commodity{" +
"name='" + name + '\'' +
", price=" + price +
", sales=" + sales +
", like=" + like +
'}';
}
//省略 get/set..
}
上面的 compareTo(Object o) 方法中,如果隻是根據對象的一個屬性進行排序...
可以直接使用一個基本資料類型包裝類,進行 campareTo()
CommodityTest.Java
import java.util.Arrays;
/** 測試類 */
public class CommodityTest {
public static void main(String[] args) {
Commodity[] commodities = new Commodity[5];
commodities[0] = new Commodity("a",1,1,1);
commodities[1] = new Commodity("b", 1,1,1 );
commodities[2] = new Commodity("c", 2,1,1 );
commodities[3] = new Commodity("d", 3,1,1 );
commodities[4] = new Commodity("a", 4,1,1 );
System.out.println("第一次周遊數組:");
for (Commodity commodity : 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 (Commodity commodity : 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>);
實作:
- 可以将
接口實作類傳遞給 sort(T[],Comparator<? super T>) 方法,進而允許在排序順序上實作精确控制。Comparator
-
當作内部類,直接傳遞給方法,内部類中重寫Comparator
比較o1和o2的大小int compare(Object o1, Object o2)方法
定制排序Demo
ComparatorTest.Java
import java.util.Arrays;
import java.util.Comparator;
/** ComparatorTest測試Demo */
public class ComparatorTest {
//直接拿String 類進行操作, String類本身實作了 comparable接口;
public static void main(String[] args) {
/** 混亂的String[] */
String[] arr = new String[]{"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,new Comparator(){
//重寫compare(Object o1, Object o2) 方法
@Override
public int compare(Object o1, Object o2) {
//類型判斷全棧類型轉換
if(o1 instanceof String && o2 instanceof String){
String s1 = (String) o1;
String s2 = (String) o2;
return -s1.compareTo(s2);
}
throw new RuntimeException("輸入的資料類型不一緻");
}
});
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 long
float double
boolean
char
及對應的
包裝類
-
Integer Byte Short Long
Float Double
Boolean
Character
位于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 */
public class PackClass {
public static void main(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.構造函數
Integer c1 = new Integer("540");
//2.自動裝箱
Integer c2 = 540;
//3.使用提供的 valueof( int/String );
// 構造函數方式已經被淘汰了... 使用String 注意String必須滿足是數字元, 不可以是 abc...
Integer c3 = Integer.valueOf("540");
//因為 Integer 是對象了,每一個對象都會又一個對應棧位址, == 比較位址是以傳回false
System.out.println(c1==c2);
System.out.println(c1==c3);
System.out.println(c2==c3);
//即使這樣也不例外!
Integer c22 = 540;
System.out.println(c2==c22);
//但 Integer 和 int 進行比較是直接比較值, 底層會進行 "自動拆箱"
int c33 = 540;
System.out.println(c3==c33);
//Integer 和 int 可以進行,數值計算/比較~
System.out.println(c3+c33);
//自動裝箱 拆箱
Integer w = 123;
System.out.println("自動裝箱:"+w);
int w1 = new Integer("123");
System.out.println("自動拆箱:"+w1);
System.out.println("自動裝箱拆箱就是: 基本資料類型 和 引用類型(包裝類), 之間的互相轉換~");
//String 包裝類 基本資料類型 互相轉換
/** 基本類型轉換為字元串(3) */
int c = 10;
//使用包裝類的 toString() 方法
String str1 = Integer.toString(c);
//使用String類的 valueOf() 方法
String str2 = String.valueOf(c);
//用一個空字元串加上基本類型,得到的就是基本類型資料對應的字元串
String str3 = c + "";
/** 字元串轉換為基本類型 */
String str = "8";
//調用包裝類的parseXxx()靜态方法
int d = Integer.parseInt(str);
//調用包裝類的valueOf()方法轉換為基本類型的包裝類,會自動拆箱
int e = Integer.valueOf(str);
/** 字元串轉換為包裝類 */
//通過構造函數 字元參數
//通過valueof("");
Integer integer = 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表達式在文本框中顯示時,結果為0
int不适合作為web層的表單資料的類型
-
Integer提供了多個與整數相關的操作方法
将一個字元串轉換成整數,Integer中還定義了表示整數的最大值和最小值的常量
本文由部落格一文多發平台 OpenWrite 釋出!