java中treemap_Java中TreeMap集合讲解
1.TreeSet介紹
TreeSet是一個有序集合,可以以任意順序將元素插入到集合中,在對集合進行遍歷的時候,每個元素將自動按照排序后的順序呈現。底層使用的是二叉樹(更具體點是紅黑樹)實現,對于元素之間排序,如果不指定自定義的比較器Comparator,那么插入的對象必須實現Comparable接口,元素按照實現此接口的compareTo()方法去排序。如果指定了自定義的比較器Comparator,優先使用Comparator去對元素進行排序。比較規則決定了元素是否可以重復,以及元素的排序結果。
2.特點保存的元素按照一定的規則有序
可自定義排序規則
非線程安全
3.存儲Integer類型元素import java.util.TreeSet;
public class DemoTreeSet {
public static void main(String[] args) {
TreeSet ts = new TreeSet<>();
ts.add(1); //自動裝箱
ts.add(7);
ts.add(3);
ts.add(5);
ts.add(3); //重復元素
System.out.println(ts);
}
}
輸出:[1, 3, 5, 7]
看上面代碼的輸出,不僅輸出元素有序,而且去除了重復元素3,我們在存元素的時候,并不是按照1,3,5,7的順序存儲的,但是遍歷卻是按照順序排列的。為什么呢?
前面我們說過,TreeSet在存對象的時候,如果不指定自定義的比較器,那么存儲的對象必須實現Comparable接口,好,我們去看下Integer類有沒有實現此接口。public final class Integer extends Number implements Comparable {
//省略其他代碼
//......
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
}
分析:
通過Integer源碼可知,它滿足TreeSet的要求,實現了Comparable接口中唯一的抽象方法compareTo(),在此方法內部又調用了一個compare()方法去定義比較規則,返回值是0,1,或者-1。前面說過,TreeSet底層是二叉樹實現的,當存儲元素的時候,會調用比較規則方法和二叉樹上的元素一一比較,如果要插入的元素比當前元素小就到左子樹去比較,如果比當前元素大,就到右子樹去比較,直到當前元素的左或者右子樹為空,就插入此元素。如果在比較過程中,出現當前元素等于要插入的元素,那么此元素不插入,例如上例中最后一個元素3被過濾掉了,這樣也就保證了Set的元素唯一性。
自定義比較器
前面說過,如果我們自定義了比較器Comparator,那么集合會優先使用自定義的比較器去對元素進行排序,好,我們現在想讓集合中的Integer元素按照倒序排列,應該如何實現呢?先來查看JDK文檔:
上圖中紅框標注的構造方法就是我們需要的,這里需要傳入一個Comparator接口類型的對象,我們當然可以自定義一個類然后實現Comparator接口,然后再new一個對象當作參數傳入TreeSet()的構造方法,但是為了方便,我們使用匿名類實現。在此之前,我們先看下Comparator接口都有什么抽象方法。
此接口只有兩個抽象方法,我們先不用管equals()方法,定義排序規則需要在compare()這個方法。好,我們來實現一下集合中元素倒序排序。import java.util.Comparator;
import java.util.TreeSet;
public class DemoTreeSet {
public static void main(String[] args) {
TreeSet ts = new TreeSet<>(new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
if(o1 == o2) return 0;
return o1 < o2 ? 1 : -1;
}
});
ts.add(1); //自動裝箱
ts.add(7);
ts.add(3);
ts.add(5);
ts.add(3);
System.out.println(ts);
}
}
輸出:[7, 5, 3, 1]
分析:
1、讀者可能發現,Comparator接口明明有兩個抽象方法,為什么只實現了compare(),很簡單。我們知道匿名類也是一個類,只要是類就會默認繼承Object類,那么就會默認繼承Object類的equals()方法,所以其實我們已經使用了從Object類繼承的方法去實現了Comparator接口的equals()方法。
2、我們在compare()方法中定義了排序規則,和Integer類中實現的方式正好相反,小于返回1,大于返回-1,等于返回0,所以輸出的元素就是倒序了。由于我們在TreeSet中自定義了比較器,所以Integer類的比較規則就失效了。
4.存儲自定義對象Student類
public class Student implements Comparable{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student o) {
return this.age - o.age;
}
}import java.util.TreeSet;
public class DemoTreeSet {
public static void main(String[] args) {
TreeSet ts = new TreeSet<>();
ts.add(new Student("張廷玉",43));
ts.add(new Student("納蘭明珠",80));
ts.add(new Student("索額圖",79));
System.out.println(ts);
}
}
輸出:
[Student [name=張廷玉, age=43], Student [name=索額圖, age=79], Student [name=納蘭明珠, age=80]]
首先我們定義了一個Student類,前面說過,如果沒有自定義比較器,TreeSet集合存儲的對象元素必須實現Comparable接口,這里我們的Student類實現了此接口,并且實現了此接口的唯一抽象方法compareTo(),這里我們是按照學生年齡排序(升序)。如果這里不實現Comparable接口,那么會報?java.lang.ClassCastException異常,意思就是這里存的元素不是Comparable類型的。
自定義比較器
我們用自定義比較器來實現一個小案例。這里我們對學生首先按照年齡進行排序,如果年齡相同,我們再按照名字的長度進行排序,都是升序,來看看我們怎么實現它。public class Student{
private String name;
private int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
import java.util.Comparator;
import java.util.TreeSet;
public class DemoTreeSet {
public static void main(String[] args) {
TreeSet ts = new TreeSet<>(new Comparator() {
@Override
public int compare(Student o1, Student o2) {
int num = o1.getAge() - o2.getAge();
return num == 0 ? o1.getName().length() - o2.getName().length() : num;
}
});
ts.add(new Student("張廷玉",43));
ts.add(new Student("納蘭明珠",80));
ts.add(new Student("索額圖",79));
ts.add(new Student("蘇麻喇姑",79));
for (Student student : ts) {
System.out.println(student);
}
}
}
輸出:
Student [name=張廷玉, age=43]
Student [name=索額圖, age=79]
Student [name=蘇麻喇姑, age=79]
Student [name=納蘭明珠, age=80]
由于我們在TreeSet中自定義了比較器,這里的Student類不需要實現Comparable接口了。我們來看compare()方法內部,首先計算比較的元素的年齡差num,如果num不等于0,那么我們還是按照年齡排序,如果年齡相同,那么我們返回元素名字長度的差,也就是說年齡相同,我們按照名字長度進行排序。從輸出可以看出,索額圖和蘇麻喇姑的年齡相同,但是索額圖名字長度要小于蘇麻喇姑,所以索額圖排在了蘇麻喇姑的前面輸出。
至此!如何使用TreeSet去存儲對象以及內部的排序原理我們就講完了,有時間自己動手去實現一下,多思考為什么要這樣,眼高手低是程序員一大忌諱。如果不懂的讀者可以在下面留言!
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的java中treemap_Java中TreeMap集合讲解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 1299元起!新款华为MatePad S
- 下一篇: java 事务的提出者_java中什么是