java學習-排序及加密簽名時數據排序方式
排序有兩種,
基本數據類型的包裝類Integer, Float, Double,Long,Byte等都實現的Comparable接口,用於列表List或數組arrays的排序
Comparable<Integer>接口方法的實現,對象列表的升序降序接口
我們通過重寫改接口方法,可以對列表進行升序或降序排列。
public int compareTo(T o);
This interface imposes a total ordering on the objects of each class that implements it. This ordering is referred to as the class‘s natural ordering
此接口對實現它的每個類的對象強加一個默認排序。這種排序被稱為類的自然排序,類的compareTo方法被稱為其自然比較方法。
Lists (and arrays) of objects that implement this interface can be sorted automatically by Collections.sort
(and Arrays.sort
).
只有實現的這個接口的對象list列表或array數組才可以使用sort方法讓列表或數組的元素被自動排序
只需要實現compareTo()方法即可
public int compareTo(){}這個比較方法,,
如果要將對象列表進行升序排序,則第i個元素和第i+1元素 要滿足a[i]>a[i+1] 返回1 a[i]<a[i+1] 返回-1 a[i]=a[i+1] 返回0
如果要將對象列表進行降序排序 要滿足 a[i]>a[i+1] 返回-1 a[i]<a[i+1] 返回1 a[i]=a[i+1] 返回0
Collections.sort方法實現的就是按照此比較的東西排列 升序(從小到大): if(price < o.price){ return -1; } if(price > o.price){ return 1; } 降序(從大到小): if(price < o.price){ return 1; } if(price > o.price){ return -1; }
//將對象按價格進行升序排序 @Override public int compareTo(flower o) { //首先比較price,如果price相同返回0 if(price < o.price){ return -1; } if(price > o.price){ return 1; } return 0; }
為什麽升序 返回值為1時,是n的值要大於n+1的值,而返回值為-1時n的值要小於n+1呢?
這個要查看源碼才可以知道原理。(不好奇的可以不看哦^~^)
由於這個List.sort()這個排序方法時使用二分排序,源碼如下,
private static void binarySort(Object[] a, int lo, int hi, int start) { assert lo <= start && start <= hi; if (start == lo) start++; for ( ; start < hi; start++) { Comparable pivot = (Comparable) a[start]; // Set left (and right) to the index where a[start] (pivot) belongs int left = lo; int right = start; assert left <= right; /* * Invariants: * pivot >= all in [lo, left). * pivot < all in [right, start). */ while (left < right) { int mid = (left + right) >>> 1; if (pivot.compareTo(a[mid]) < 0) right = mid; else left = mid + 1; } assert left == right; /* * The invariants still hold: pivot >= all in [lo, left) and * pivot < all in [left, start), so pivot belongs at left. Note * that if there are elements equal to pivot, left points to the * first slot after them -- that‘s why this sort is stable. * Slide elements over to make room for pivot. */ int n = start - left; // The number of elements to move // Switch is just an optimization for arraycopy in default case switch (n) { case 2: a[left + 2] = a[left + 1]; case 1: a[left + 1] = a[left]; break; default: System.arraycopy(a, left, a, left + 1, n); } a[left] = pivot; } }
while (left < right) { int mid = (left + right) >>> 1; if (pivot.compareTo(a[mid]) < 0) right = mid; else left = mid + 1; }
這個值是和已排序的數據的中間的數據進行比較,provot.compareTo(a[mid])
註意看,上面的a[mid]是作為比較方法的參數。
當小於0,也就是值為-1時,是我們要插入的數據作為調用方,
小於0時,該數據插入到前面,
大於0時,數據插入到後面
思維慣性以為升序就是第一個元素比第二個元素小。obj1.compareTo(Object obj2)
即obj1=2是第一個元素,obj2=8是第二個元素
那麽我們升序時,如果obj1小於obj2,返回值為-1,則會將obj2插入到obj1前面,,排序前【2, 8】這樣排序完後卻變成了,,【8, 2】
這跟我們想要的升序數據不一樣,
原因是java的二分法進行比較了是,,obj2.compareTo(obj1),,與我們想的剛好相反,
所以我們返回的值取反就可以變成升序了,
如這個消費類,,只給出部分代碼
public class ConsumInfo implements Comparable<ConsumInfo> { public double price;
public String name;
public Consuminfo(double price, String name){
this.price = price;
this.name = name;
} @Override public int compareTo(ConsumInfo o) { //首先比較price,如果price相同 if(price < o.price){ return -1; } if(price > o.price){ return 1; } return 0; } }
ConsumInfo consumInfo1 = new ConsumInfo("consumInfo1", 400.0); ConsumInfo consumInfo2 = new ConsumInfo("consumInfo2", 200.0);
List<ConsumInfo> list = new ArrayList<ConsumInfo>(); list.add(consumInfo1); list.add(consumInfo2); System.out.println("排序前:"); for(ConsumInfo consumInfo : list ){ System.out.println(consumInfo); } Collections.sort(list);//排序 System.out.println("排序後:");//排序後 for(ConsumInfo consumInfo :list){ System.out.println(consumInfo); }
控制臺輸出信息為:
排序前: ConsumInfo [name=consumInfo1, price=400.0] ConsumInfo [name=consumInfo2, price=200.0] 排序後: ConsumInfo [name=consumInfo2, price=200.0] ConsumInfo [name=consumInfo1, price=400.0]
上面是最簡單的兩個元素進行排序,
第一次,往已排序列表中插入第一個元素,即數組中只有一個已排好序的元素,a[0] = consumInfo1
第二次時,left為0,right為1,進入while循環中,
mid=0,privot=consumInfo2
即consumInfo2.comparTo(a[0])
當方法的返回值小於0時,consumInfo2會插入在consumInfo1之前,
大於0時,會在consumInfo1之後
進行比較時,consumInfo2.price<consumInfo1.price 返回值小於0,也就是consumInfo1的值比較大,插入在1之前
java學習-排序及加密簽名時數據排序方式