(有坑)如何正確實現Comparator介面
最近使用者報告了一個crash,錯誤堆疊如下:
java.lang.IllegalArgumentException: Comparison method violates its general contract! at java.util.TimSort.mergeHi(TimSort.java:864) at java.util.TimSort.mergeAt(TimSort.java:481) at java.util.TimSort.mergeForceCollapse(TimSort.java:422) at java.util.TimSort.sort(TimSort.java:219) at java.util.TimSort.sort(TimSort.java:169) at java.util.Arrays.sort(Arrays.java:2010) at java.util.Collections.sort(Collections.java:1883) at com.xxx.model.c.a(Unknown Source) at com.xxx.view.de.doInBackground(Unknown Source) at android.os.AsyncTask$2.call(AsyncTask.java:288) at java.util.concurrent.FutureTask.run(FutureTask.java:237) at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) at java.lang.Thread.run(Thread.java:841)
這個app運行了一年多還是第一次碰到這個crash。TimSort又是什麼鬼?
簡單的講TimSort是一個優化後的merge sort,比原來的merge sort更穩定、更快。
兩大特點:
1. 對已接近排序和倒序的陣列排序速度異常快。
2. 最差情況仍是O(n*log(n))
JDK7的排序演算法實現改為TimSort。java.util.TimSort的類註釋。
/** * A stable, adaptive, iterative mergesort that requires far fewer than * n lg(n) comparisons when running on partially sorted arrays, while * offering performance comparable to a traditional mergesort when run * on random arrays. Like all proper mergesorts, this sort is stable and * runs O(n log n) time (worst case). In the worst case, this sort requires * temporary storage space for n/2 object references; in the best case, * it requires only a small constant amount of space. * * This implementation was adapted from Tim Peters's list sort for * Python, which is described in detail here: * * http://svn.python.org/projects/python/trunk/Objects/listsort.txt * * Tim's C code may be found here: * * http://svn.python.org/projects/python/trunk/Objects/listobject.c * * The underlying techniques are described in this paper (and may have * even earlier origins): * * "Optimistic Sorting and Information Theoretic Complexity" * Peter McIlroy * SODA (Fourth Annual ACM-SIAM Symposium on Discrete Algorithms), * pp 467-474, Austin, Texas, 25-27 January 1993. * * While the API to this class consists solely of static methods, it is * (privately) instantiable; a TimSort instance holds the state of an ongoing * sort, assuming the input array is large enough to warrant the full-blown * TimSort. Small arrays are sorted in place, using a binary insertion sort. * * @author Josh Bloch */
具體演算法原理這裡不做細究,有興趣的可以研究一下上面註釋中的連結或者論文。
解決方法為在實現Comparator<T>介面時,必須嚴格遵循實現約束,否則會導致執行時異常。
具體約束為:
- sgn(compare(x, y)) == -sgn(compare(y, x)) for all x and y.
- ((compare(x, y)>0) && (compare(y, z)>0)) implies compare(x, z)>0.
- compare(x, y)==0 implies that sgn(compare(x, z))==sgn(compare(y, z)) for all z.
錯誤示例:(JDK6下執行正常,JDK7下會crash)
public class XXXComparator implements Comparator<SomeModel> { // 當lhs==rhs時,compare(lhs,rhs)== -1, compare(rhs, lhs)==-1 違背約束1 @Override public int compare(SomeModel lhs, SomeModel rhs) { if (rhs.value < lhs.value) { return 1; } else { return -1; } } }
參考:
相關推薦
(有坑)如何正確實現Comparator介面
最近使用者報告了一個crash,錯誤堆疊如下: java.lang.IllegalArgumentException: Comparison method violates its general contract! at java.util.TimSort.merge
1010 Radix - 進位制轉換(有坑)
思路: 這題有坑啊 (1)z表示36並不意味著只到36進位制,最小2進位制,最大進位制=另一個數的值 (2)可能會超時,用二分 (3)用long long!在二分過程中會溢位,所以要特判,當溢位時說明書過大,right=mid-1 程式碼如下: #include<ios
PAT——乙級1036&乙級1027(有坑)
乙級1036 1036 跟奧巴馬一起程式設計 (15 point(s)) 美國總統奧巴馬不僅呼籲所有人都學習程式設計,甚至以身作則編寫程式碼,成為美國曆史上首位編寫計算機程式碼的總統。2014 年底,為慶祝“電腦科學教育周”正式啟動,奧巴馬編寫了很
181C】序列(字首和,二分,可用set維護)(有坑)
題幹: 小a有n個數,他想把他們劃分為連續的權值相等的k段,但他不知道這是否可行。 每個數都必須被劃分 這個問題對他來說太難了,於是他把這個問題丟給了你。 輸入描述: 第一行為兩個整數n,q,分別表示序列長度和詢問個數。 第二行有n個數,表示序列中的每個數。 接下來
MySQL中ORDER BY與LIMIT一起使用(有坑)
1. 現象與問題 ORDER BY排序後,用LIMIT取前幾條,發現返回的結果集的順序與預期的不一樣 下面是我遇到的問題: 可以看到,帶LIMIT與不帶LIMIT的結果與我預期的不一樣,而且“很不可思議”,真是百思不得其解 後來百度了一下,如
【CodeForces - 864C】Bus (模擬,有坑)
題幹: A bus moves along the coordinate line Ox from the point x = 0 to the point x = a. After starting from the point
【 CodeForces - 864B】Polycarp and Letters(水題,字串,有坑)
題幹: Polycarp loves lowercase letters and dislikes uppercase ones. Once he got a string sconsisting only of lowercase and uppercase Latin lett
如何實現多執行緒?實現多執行緒為什麼要調start,而不是run方法?(繼承Thread類、實現Ruable介面、Callable<V>)
什麼是程序? 作業系統中一個程式的執行週期(從開啟到關閉)。程序是具有一個或多個執行緒的執行緒組。 什麼是執行緒? 一個程序可以同時執行多個任務,任務就是執行緒,一個程序至少有一個執行緒。 執行緒執行在程序內部,執行緒是輕量級程序。 程序和執行緒比較:
【CodeForces - 151D】Quantity of Strings (字串問題,思維推導,有坑)
題幹: Just in case somebody missed it: this winter is totally cold in Nvodsk! It is so cold that one gets funny thoughts. For example, let's say the
【CodeForces - 270C】Magical Boxes (思維,進位制,有坑)
題幹: Emuskald is a well-known illusionist. One of his trademark tricks involves a set of magical boxes. The essence of the trick is in packing the
【CodeForces - 340B 】Maximal Area Quadrilateral (計算幾何,列舉,有坑)
題幹: Iahub has drawn a set of n points in the cartesian plane which he calls "special points". A quadrilateral is a simple polygon withou
【CodeForces - 298C】Parity Game (思維,有坑)
題幹: You are fishing with polar bears Alice and Bob. While waiting for the fish to bite, the polar bears get bored. They come up with a game. First
CS231n-KNN實現(附坑)
從效果看來,KNN並不適合影象識別,它的識別更多基於背景,而不是圖片的語義主體。所以在實際應用中我們一般不適用KNN識別影象,但是在學習過程中,通過KNN演算法我們可以學習到影象識別的整個流程,還是有些許幫助的 影象識別流程 無論是哪種分類演算法,影象識別的流程主要為以下流程
(有坑點)JoyOI1359收入計劃(二分)
高考結束後,同學們大都找到了一份臨時工作,渴望掙得一些零用錢。從今天起,Matrix67將連續工作N天(1<=N<=100 000)。每一天末他可以領取當天及前面若干天裡沒有領取的工資,但
985D】Sand Fortress (二分,貪心,思維構造,技巧,有坑)
題幹: You are going to the beach with the idea to build the greatest sand castle ever in your head! The beach is not as three-dimensional a
2033 】Alphacode (dp,有坑)
題幹: Alice and Bob need to send secret messages to each other and are discussing ways to encode their messages: Alice: "Let's just use a
AVL樹插入刪除演算法詳解(有圖) -- C++語言實現
一:AVL樹介紹 AVL樹本質上還是一棵二叉搜尋樹,它的特點是: 1.本身首先是一棵二叉搜尋樹。 2.帶有平衡條件:每個結點的左右子樹的高度之差的絕對值(平衡因子)最多為1。在本文中用分別用-1,0,1定義左邊樹高,等高,右邊樹高。平衡因子用m_bf表示。 也就是說,AV
上千萬或上億資料(有重複),統計其中出現次數最多的N個數據. C++實現
上千萬或上億的資料,現在的機器的記憶體應該能存下。所以考慮採用hash_map/搜尋二叉樹/紅黑樹等來進行統計次數。然後就是取出前N個出現次數最多的資料了,可以用第2題提到的堆機制完成。 #in
伺服器介面呼叫日誌檔案記錄(有格式)
/** * * @Title: writeLocationLog * @Description: 伺服器上寫入操作日誌 * @param type "input"表示入參,“output”表示出參 * @param xml 具體的出入參資訊 * @para
演算法C++實現(有註釋):統計數字某位數的個數,用隨機函式產生100個[0,99]範圍內的隨機整數, 統計數字的個位上的數字分別為0,1,2,3,4,5,6,7,8,9的數的個數,並打印出來。
#include<iostream> #include<cstdlib>// #include <stdlib.h> void srand( unsigned seed ); //功能: 設定rand()隨機序列種子。對於給定的種子se