Java之TreeSet和TreeMap的兩種排序方式解讀
一、TreeSet比較常見(jiàn)形式
TreeSet可以對(duì)元素按照某種規(guī)則進(jìn)行排序:
public class test {
public static void main(String[] args) {
Set<Integer> s1=new TreeSet<>();
s1.add(23);
s1.add(3);
s1.add(2);
s1.add(13);
s1.add(63);
s1.add(25);
s1.add(22);
System.out.println(s1);
Set<String> s2=new TreeSet<>();
s2.add("c");
s2.add("f");
s2.add("a");
s2.add("t");
s2.add("j");
s2.add("b");
s2.add("n");
System.out.println(s2);
}
}
如果添加的是對(duì)象(Studen)時(shí),如何排序呢?
class Student{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
}
public class test {
public static void main(String[] args) {
Set<Student> s1=new TreeSet<Student>();
s1.add(new Student("zhangsan",23));
s1.add(new Student("lisi",22));
s1.add(new Student("wangwu",32));
s1.add(new Student("huyijie",19));
System.out.println("s1===================");
for(Student s:s1){
System.out.println(s);
}
}
}
會(huì)發(fā)現(xiàn)無(wú)法排序。
二、解決方法
1 自然排序
- TreeSet存入數(shù)據(jù)后自動(dòng)調(diào)用元素的compareTo(Object obj)方法,自動(dòng)對(duì)數(shù)據(jù)進(jìn)行排序,所以輸出的數(shù)據(jù)是經(jīng)過(guò)排序的數(shù)據(jù)
- 注:compareTo方法返回值有:負(fù)數(shù)、零、整數(shù),分別表示小于、等于、大于。
- 對(duì)于存入自定義的對(duì)象元素時(shí),要重寫(xiě)元素的compareTo(Object obj)方法
- 元素定義時(shí),需要實(shí)現(xiàn)Comparable<T>接口
class Student implements Comparable<Student>{
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public Student() {
}
@Override
public int compareTo(Student o) {
return o.age-this.age; //從大到小輸出
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class test {
public static void main(String[] args) {
Set<Student> s1 = new TreeSet<Student>((o1, o2) -> o1.getAge() - o2.getAge());
s1.add(new Student("zhangsan", 23));
s1.add(new Student("lisi", 22));
s1.add(new Student("wangwu", 32));
s1.add(new Student("huyijie", 19));
System.out.println("s1===================");
for (Student s : s1) {
System.out.println(s);
}
}
}
2 自定義比較器排序
- 這種方法需要一個(gè)新的類實(shí)現(xiàn)Comparator<T>接口,重寫(xiě)其中的Compare方法
- TreeSet當(dāng)元素不具備比較性,或者比較性不是所需要的時(shí)候,可以使TreeSet集合具有比較性,定義比較器,將比較器作為參數(shù)傳給TreeSet集合,比較器需要實(shí)現(xiàn)Comparator接口,當(dāng)元素具備比較性和比較器同時(shí)出現(xiàn)時(shí),以比較器為準(zhǔn)。
class TestComparator implements Comparator<Student>{
@Override
public int compare(Student o1, Student o2) {
return o1.getAge()-o2.getAge();
}
}
//(o1, o2) -> o1.getAge() - o2.getAge()
public class test {
public static void main(String[] args) {
Set<Student> s1 = new TreeSet<Student>(new TestComparator());
s1.add(new Student("zhangsan", 23));
s1.add(new Student("lisi", 22));
s1.add(new Student("wangwu", 32));
s1.add(new Student("huyijie", 19));
System.out.println("s1===================");
for (Student s : s1) {
System.out.println(s);
}
}
}
也可以通過(guò)匿名內(nèi)部類簡(jiǎn)化,
public class test {
public static void main(String[] args) {
Set<Student> s1 = new TreeSet<Student>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o2.getAge()-o1.getAge();
}
});
s1.add(new Student("zhangsan", 23));
s1.add(new Student("lisi", 22));
s1.add(new Student("wangwu", 32));
s1.add(new Student("huyijie", 19));
System.out.println("s1===================");
for (Student s : s1) {
System.out.println(s);
}
}
}可再通過(guò)Lambda表達(dá)式簡(jiǎn)化,


三、TreeMap按值排序
首先說(shuō)一下如果Map對(duì)key進(jìn)行從小到大默認(rèn)排序是創(chuàng)建TreeMap對(duì)象。Map<Integer,Integer> maps = new TreeMap<>();就行了。
那么如何實(shí)現(xiàn)按value排序呢? (把TreeMap的EntrySet轉(zhuǎn)換成list,然后使用Collections.sort排序)
這里使用的是java.util.Collections類實(shí)現(xiàn)排序,將Map轉(zhuǎn)成List,再自定義比較器,代碼如下:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
public class MapValSort {
public static void main(String[] args) {
Map<String, Integer> maps = new TreeMap<String, Integer>();
maps.put("zhangsan", 22);
maps.put("lisi", 24);
maps.put("wangwu", 18);
maps.put("zhaoliu", 22);
//自定義比較器
Comparator<Map.Entry<String, Integer>> valCmp = new Comparator<Map.Entry<String,Integer>>() {
@Override
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
// TODO Auto-generated method stub
return o2.getValue()-o1.getValue(); // 降序排序,如果想升序就反過(guò)來(lái)
}
};
//將map轉(zhuǎn)成List,map的一組key,value對(duì)應(yīng)list一個(gè)存儲(chǔ)空間
List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String,Integer>>(maps.entrySet()); //傳入maps實(shí)體
Collections.sort(list,valCmp); // 注意此處Collections 是java.util包下面的,傳入List和自定義的valCmp比較器
//輸出map
for(int i=0;i<list.size();i++) {
System.out.println(list.get(i).getKey() + " = " + list.get(i).getValue());
}
}
}四、關(guān)于compareTo方法
- ompareTo() 方法用于將 Number 對(duì)象與方法的參數(shù)進(jìn)行比較??捎糜诒容^ Byte, Long, Integer等。
- compareTo方法從第一位開(kāi)始比較, 如果遇到不同的字符,則馬上返回這兩個(gè)字符的ascii值差值.返回值是int類型
返回參與比較的前后兩個(gè)字符串的asc碼的差值,如果兩個(gè)字符串首字母不同,則該方法返回首字母的asc碼的差值
String a1 = "a"; String a2 = "c"; System.out.println(a1.compareTo(a2));//結(jié)果為-2
即參與比較的兩個(gè)字符串如果首字符相同,則比較下一個(gè)字符,直到有不同的為止,返回該不同的字符的asc碼差值
String a1 = "aa"; String a2 = "ad"; System.out.println(a1.compareTo(a2));//結(jié)果為-3
如果兩個(gè)字符串不一樣長(zhǎng),可以參與比較的字符又完全一樣,則返回兩個(gè)字符串的長(zhǎng)度差值
String a1 = "aa"; String a2 = "aa12345678"; System.out.println(a1.compareTo(a2));//結(jié)果為-8
- 返回為正數(shù)表示a1>a2, 返回為負(fù)數(shù)表示a1<a2,返回0表示a1==a2。
數(shù)字類型不能用compareTo,nt跟int的比較不能用compareTo方法,直接用大于(>) 小于(<) 或者 等于(==) 不等于(!=)來(lái)比較即可
int型可以直接比較,所以沒(méi)有用到compareTo比較,如果聲明的是Date、String、Integer、或者其他的,可以直接使用compareTo比較,
Integer n1 = 5; Integer n2 = 6; System.out.println(n1.compareTo(n2));//-1
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot優(yōu)雅統(tǒng)計(jì)接口耗時(shí)實(shí)戰(zhàn)中的四種高效方案
這篇文章主要為大家詳細(xì)介紹了SpringBoot優(yōu)雅統(tǒng)計(jì)接口耗時(shí)實(shí)戰(zhàn)中的四種高效方案,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2026-01-01
Spring模塊詳解之Spring ORM和Spring Transaction詳解
Spring ORM 是 Spring 框架的模塊之一,旨在簡(jiǎn)化與 JPA、Hibernate、JDO 等 ORM 工具的集成,通過(guò)提供統(tǒng)一的 API 和模板類,如 HibernateTemplate 和 JpaTemplate,Spring ORM 使開(kāi)發(fā)者可以更便捷地執(zhí)行數(shù)據(jù)庫(kù)操作,感興趣的朋友跟隨小編一起看看吧2024-09-09
Project?Reactor源碼解析publishOn使用示例
這篇文章主要為大家介紹了Project?Reactor源碼解析publishOn使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
如何用Java來(lái)進(jìn)行文件切割和簡(jiǎn)單的內(nèi)容過(guò)濾的實(shí)現(xiàn)
這篇文章主要介紹了如何用Java來(lái)進(jìn)行文件切割和簡(jiǎn)單的內(nèi)容過(guò)濾的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-01-01
java實(shí)現(xiàn)求只出現(xiàn)一次的數(shù)字
本文主要介紹了java實(shí)現(xiàn)求只出現(xiàn)一次的數(shù)字,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
Java實(shí)現(xiàn)五子棋網(wǎng)絡(luò)版
這篇文章主要為大家詳細(xì)介紹了基于Java編寫(xiě)的網(wǎng)絡(luò)五子棋,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-03-03
mybatis 插件: 打印 sql 及其執(zhí)行時(shí)間實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇mybatis 插件: 打印 sql 及其執(zhí)行時(shí)間實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-06-06
java 用遞歸獲取一個(gè)目錄下的所有文件路徑的小例子
還是日志的問(wèn)題,log4j生成的日志文件,自動(dòng)保存到月份所在的文件夾中,需要獲取到所有的日志文件,包括文件夾2013-09-09
Java之String字符串在JVM中的存儲(chǔ)及其內(nèi)存地址的問(wèn)題
這篇文章主要介紹了Java之String字符串在JVM中的存儲(chǔ)及其內(nèi)存地址的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07

