摘要:最近一直在做底層方面的研究,所以這段時間就沒寫相關的東西,但恰巧今天同事問我一個問題,在幫他解決完這個問題之后,我發現,這個問題對新手來說還是非常容易犯的,所以在這里記錄下。首先看下面這段代碼這段代碼的功能就是對進行排序,內元素類型是。
最近一直在做底層方面的研究,所以這段時間就沒寫java相關的東西,但恰巧今天同事問我一個問題,在幫他解決完這個問題之后,我發現,這個問題對java新手來說還是非常容易犯的,所以在這里記錄下。
首先看下面這段代碼:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; public class Test { public static void main(String[] args) { Listl = new ArrayList<>(); for (int i = 0; i < 100000; i++) { l.add(ThreadLocalRandom.current().nextLong()); } l.sort((o1, o2) -> (int) (o1 - o2)); // l.sort(Long::compare); } }
這段代碼的功能就是對list進行排序,list內元素類型是long。
一眼看上去好像沒啥大問題,執行看下:
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract! at java.base/java.util.TimSort.mergeLo(TimSort.java:781) at java.base/java.util.TimSort.mergeAt(TimSort.java:518) at java.base/java.util.TimSort.mergeCollapse(TimSort.java:448) at java.base/java.util.TimSort.sort(TimSort.java:245) at java.base/java.util.Arrays.sort(Arrays.java:1516) at java.base/java.util.ArrayList.sort(ArrayList.java:1749) at io.ytcode.game.test/test.Test.main(Test.java:14)
額,報錯了(可能需要多執行幾次才會報錯,但并不影響本文內容),為什么呢?
這段代碼大部分邏輯用的都是官方的api,所以這些地方肯定是沒問題的,需要我們自己寫邏輯的唯一的地方就是list.sort方法傳遞的參數:Comparator。
看下我們怎么寫的,我們返回了 (int) (o1 - o2),看出問題了嗎?
o1 - o2的結果還是long啊,如果這個值大于int范圍,在我們把它轉成int后,結果就溢出處理了,這時,該表達式返回的結果和我們預期的結果就不相同了。
我估計很多人都踩過這坑吧。
那正確的解決方式是什么呢?
把上面程序中的sort行注釋掉,用它下面Long::compare的sort行,再試試是不是就可以了。
看下Long::compare的對應實現:
// java.lang.Long public static int compare(long x, long y) { return (x < y) ? -1 : ((x == y) ? 0 : 1); }
這才是long的compare的標準方式!
還是那句話,官方庫帶有的方法就用官方的,這能讓你少踩很多坑。
完。
更多原創文章,請關注我微信公眾號:
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75821.html
摘要:對于程序員來說,更意味著代碼的組織,工作成員之間的協作方式。我常犯的一個錯誤是直接在或分支上直接,而團隊是不允許這樣做的。 先介紹下背景,博主由運營轉行前端,入職一個月,完成了一個相對較大的模塊。由于基礎相對薄弱,犯下了不少錯誤,故想記錄下來警醒自己和分享各位。 前端技術棧是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:對于程序員來說,更意味著代碼的組織,工作成員之間的協作方式。我常犯的一個錯誤是直接在或分支上直接,而團隊是不允許這樣做的。 先介紹下背景,博主由運營轉行前端,入職一個月,完成了一個相對較大的模塊。由于基礎相對薄弱,犯下了不少錯誤,故想記錄下來警醒自己和分享各位。 前端技術棧是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:對于程序員來說,更意味著代碼的組織,工作成員之間的協作方式。我常犯的一個錯誤是直接在或分支上直接,而團隊是不允許這樣做的。 先介紹下背景,博主由運營轉行前端,入職一個月,完成了一個相對較大的模塊。由于基礎相對薄弱,犯下了不少錯誤,故想記錄下來警醒自己和分享各位。 前端技術棧是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:原文出自本文總結了程序員常犯的個錯誤。可以看看為什么在中被設計成不可變父類和子類的構造函數以上這段代碼出現編譯錯誤,因為默認的父類構造函數未定義。如果程序員定義構造函數,編譯器將不插入默認的無參數構造函數。 原文出自:http://www.programcreek.com/2014/05/top-10-mistakes-java-developers-make/ 本文總結了J...
閱讀 2181·2021-11-19 09:55
閱讀 2637·2021-11-11 16:55
閱讀 3175·2021-09-28 09:36
閱讀 1945·2021-09-22 16:05
閱讀 3272·2019-08-30 15:53
閱讀 1806·2019-08-30 15:44
閱讀 2899·2019-08-29 13:10
閱讀 1339·2019-08-29 12:30