一.java中的compareto方法
1.返回參與比較的前后兩個字符串的asc碼的差值,如果兩個字符串首字母不同,則該方法返回首字母的asc碼的差值
String a1 = "a"; String a2 = "c"; System.out.println(a1.compareTo(a2));//結果為-2
2.即參與比較的兩個字符串如果首字符相同,則比較下一個字符,直到有不同的為止,返回該不同的字符的asc碼差值,
String a1 = "aa"; String a2 = "ad"; System.out.println(a1.compareTo(a2));//結果為-3
3.如果兩個字符串不一樣長,可以參與比較的字符又完全一樣,則返回兩個字符串的長度差值
String a1 = "aa"; String a2 = "aa12345678"; System.out.println(a1.compareTo(a2));//結果為-8
4.返回為正數表示a1>a2, 返回為負數表示a1<a2, 返回為0表示a1==a2;
5.數字類型不能用compareTo,nt跟int的比較不能用compareTo方法,直接用大於(>) 小於(<) 或者 等於(==) 不等於(!=)來比較即可
int num1 = 4; int num2 = 5; num1.compareTo(num2);//Cannot invoke compareTo(int) on the primitive type int
你可以先把你的int型變量轉換成String再進行比較
int num1 = 4; int num2 = 5; //parse int to String System.out.println((num1+"").compareTo(num2+""));//-1 System.out.println(new Integer(num1).toString(). compareTo(new Integer(num2).toString()));//-1 System.out.println(String.valueOf(num1).compareTo(String.valueOf(num2)));//-1
6.compareToIgnoreCase忽略大小寫
不考慮大小寫,按字典順序比較兩個字符串。此方法返回一個整數,它的正負號是調用 compareTo 的正負號,調用時使用了字符串的規范化版本,其大小寫差異已通過對每個字符調用 Character.toLowerCase(Character.toUpperCase(character)) 得以消除。
注意,此方法不 考慮語言環境,因此可能在某些特定的語言環境中產生不理想的排序。java.text 包提供 Collators 來完成語言環境敏感的排序。
7.int型可以直接比較,所以沒有用到compareTo比較,如果聲明的是Date、String、Integer、或者其他的,可以直接使用compareTo比較,
Integer n1 = 5; Integer n2 = 6; System.out.println(n1.compareTo(n2));//-1
二. Comparable<T>接口中的compareTo
compareTo方法內必須做非空判斷(規范問題),當然int類型就不用了。
注意事項:
1、模型必須實現Comparable<T>接口
2、Collection.sort(list)會自動調用compareTo,如果沒有這句,list是不會排序的,也不會調用compareTo方法
3、如果是數組則用Arrays.sort(a)方法
注意要非空判斷,這里實例就不判斷了
private int bookId; private String bookName; private int bookPrice; @Override public int compareTo(Book o) { // TODO Auto-generated method stub //return this.bookPrice-o.bookPrice;//按價格排序 升序 //return o.bookPrice-this.bookPrice;//按價格排序 降序 //return this.bookName.compareTo(o.bookName);//按書名排序 升序 //先按 id 再按價格 最后按書名排序 升序 int result = this.bookId - o.bookId; if(result == 0){ result =this.bookPrice - o.bookPrice; } if(result == 0){ result = this.bookName.compareTo(o.bookName); } return result; }
package com.my.test.compare; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; public class TestCompare { public static void main(String[] args) { Book b1 = new Book(1, "語文", 20); Book b2 = new Book(2, "數學", 10); Book b3 = new Book(5, "英語", 10); Book b4 = new Book(4, "化學", 50); Book b5 = new Book(3, "化學", 10); //Book b6 = null;//不能為null,Collections.sort調用compareTo會報空指針異常 List<Book> books = new ArrayList<>(); books.add(b1); books.add(b2); books.add(b3); books.add(b4); books.add(b5); System.out.println("Collections 排序前"); for (Book book : books) { System.out.println(book); } Collections.sort(books); System.out.println("Collections 排序后"); for (Book book : books) { System.out.println(book); } Book[] b = new Book[5]; System.out.println(b.length); b[0] = b1; b[1] = b2; b[2] = b3; b[3] = b4; b[4] = b5; System.out.println("Arrays 排序前" ); for (Book book : b) { System.out.println(book); } Arrays.sort(b); System.out.println("Arrays 排序后" ); for (Book book : b) { System.out.println(book); } } }
在應用中我們為了好判斷狀態,一般處理為
if(this.bookId<o.bookId){ return -1; }else if(this.bookId>o.bookId){ return 1; }else{ return 0; }
返回值為 1,0.-1:
三。 Comparator接口
源碼:
@FunctionalInterface public interface Comparator<T> { // 核心方法,用來比較兩個對象,如果o1小於o2,返回負數;等於o2,返回0;大於o2返回正數 int compare(T o1, T o2); // 好像很少用到,一般都用對象自帶的equals boolean equals(Object obj); /**-----------下面的都是JDK1.8新增的接口,挑幾個放進去----------*/ //返回反向排序比較器 default Comparator<T> reversed() { return Collections.reverseOrder(this); } //根據名字知道,先進行compare比較后,再進行一次比較 default Comparator<T> thenComparing(Comparator<? super T> other) { Objects.requireNonNull(other); return (Comparator<T> & Serializable) (c1, c2) -> { int res = compare(c1, c2); return (res != 0) ? res : other.compare(c1, c2); }; } //對int類型的key進行比較 public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) { Objects.requireNonNull(keyExtractor); return (Comparator<T> & Serializable) (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2)); } //返回正常順序的比較器 public static <T extends Comparable<? super T>> Comparator<T> naturalOrder() { return (Comparator<T>) Comparators.NaturalOrderComparator.INSTANCE; } }
一起來看一下如何使用,先來看一下JDK1.8以前的用法:
Collections.sort(books,new Comparator<Book>() { @Override public int compare(Book o1, Book o2) { // TODO Auto-generated method stub return o1.getBookPrice() - o2.getBookPrice(); } });
或者創建一個比較器
package com.my.test.compare; import java.util.Comparator; public class SimpleCompator implements Comparator<Book> { @Override public int compare(Book o1, Book o2) { // TODO Auto-generated method stub return o1.getBookPrice() -o2.getBookPrice(); } }
Collections.sort(books,new SimpleCompator());
JDK1.8以前的用法要自己手動實現Comparator接口,然后調用Collections.sort()
,傳入實現類來完成排序,非常麻煩,而JDK1.8則相對來說簡單了很多:
Collections.sort(books,(Book a, Book b) -> { return a.getBookPrice()-b.getBookPrice(); });
或者可以簡單的寫為
Collections.sort(books,(Book a, Book b) -> a.getBookPrice()-b.getBookPrice());
甚至,我們可以不使用Collections.sort:
books.sort((Book a, Book b) -> a.getBookPrice()-b.getBookPrice() );
詳見:http://www.manongjc.com/article/8005.html
compator 在 treeMap 中的 應用(基於key的排序):
treeMap默認的是基於key的從小到大 的排列
自定義排序也是基於key的,如果key object類型 可以自定義各種排序
TreeMap<String, Person> treeMap = new TreeMap<>((String a,String b)-> b.compareTo(a));//降序
TreeMap<String, Person> treeMap = new TreeMap<>((String a,String b)-> a.compareTo(b));//升序
TreeMap的按value排序(轉換成entry list 然后排序)漢字是按ascii碼排序的,不是漢語拼音
Person p1 = new Person(1, "A小紅"); Person p2 = new Person(5, "D趙明"); Person p3 = new Person(2, "W孫宇"); Person p4 = new Person(9, "C黎明"); TreeMap<String, Person> treeMap = new TreeMap<>(); treeMap.put("45", p1); treeMap.put("12", p2); treeMap.put("85", p3); treeMap.put("33", p4); List<Map.Entry<String, Person>> entries = new ArrayList<>(treeMap.entrySet()); Collections.sort(entries, (Map.Entry<String, Person> e1, Map.Entry<String, Person> e2) -> ((Person) e1.getValue()).getPersonName() .compareTo(((Person) e2.getValue()).getPersonName())); System.out.println("按名字順序排列"); for (Entry<String, Person> entry : entries) { System.out.println(entry.getValue()); }