摘要:最近一直在做底層方面的研究,所以這段時(shí)間就沒寫相關(guān)的東西,但恰巧今天同事問我一個(gè)問題,在幫他解決完這個(gè)問題之后,我發(fā)現(xiàn),這個(gè)問題對(duì)新手來說還是非常容易犯的,所以在這里記錄下。首先看下面這段代碼這段代碼的功能就是對(duì)進(jìn)行排序,內(nèi)元素類型是。
最近一直在做底層方面的研究,所以這段時(shí)間就沒寫java相關(guān)的東西,但恰巧今天同事問我一個(gè)問題,在幫他解決完這個(gè)問題之后,我發(fā)現(xiàn),這個(gè)問題對(duì)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); } }
這段代碼的功能就是對(duì)list進(jìn)行排序,list內(nèi)元素類型是long。
一眼看上去好像沒啥大問題,執(zhí)行看下:
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)
額,報(bào)錯(cuò)了(可能需要多執(zhí)行幾次才會(huì)報(bào)錯(cuò),但并不影響本文內(nèi)容),為什么呢?
這段代碼大部分邏輯用的都是官方的api,所以這些地方肯定是沒問題的,需要我們自己寫邏輯的唯一的地方就是list.sort方法傳遞的參數(shù):Comparator。
看下我們?cè)趺磳懙模覀兎祷亓?(int) (o1 - o2),看出問題了嗎?
o1 - o2的結(jié)果還是long啊,如果這個(gè)值大于int范圍,在我們把它轉(zhuǎn)成int后,結(jié)果就溢出處理了,這時(shí),該表達(dá)式返回的結(jié)果和我們預(yù)期的結(jié)果就不相同了。
我估計(jì)很多人都踩過這坑吧。
那正確的解決方式是什么呢?
把上面程序中的sort行注釋掉,用它下面Long::compare的sort行,再試試是不是就可以了。
看下Long::compare的對(duì)應(yīng)實(shí)現(xiàn):
// java.lang.Long public static int compare(long x, long y) { return (x < y) ? -1 : ((x == y) ? 0 : 1); }
這才是long的compare的標(biāo)準(zhǔn)方式!
還是那句話,官方庫帶有的方法就用官方的,這能讓你少踩很多坑。
完。
更多原創(chuàng)文章,請(qǐng)關(guān)注我微信公眾號(hào):
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/75821.html
摘要:對(duì)于程序員來說,更意味著代碼的組織,工作成員之間的協(xié)作方式。我常犯的一個(gè)錯(cuò)誤是直接在或分支上直接,而團(tuán)隊(duì)是不允許這樣做的。 先介紹下背景,博主由運(yùn)營轉(zhuǎn)行前端,入職一個(gè)月,完成了一個(gè)相對(duì)較大的模塊。由于基礎(chǔ)相對(duì)薄弱,犯下了不少錯(cuò)誤,故想記錄下來警醒自己和分享各位。 前端技術(shù)棧是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:對(duì)于程序員來說,更意味著代碼的組織,工作成員之間的協(xié)作方式。我常犯的一個(gè)錯(cuò)誤是直接在或分支上直接,而團(tuán)隊(duì)是不允許這樣做的。 先介紹下背景,博主由運(yùn)營轉(zhuǎn)行前端,入職一個(gè)月,完成了一個(gè)相對(duì)較大的模塊。由于基礎(chǔ)相對(duì)薄弱,犯下了不少錯(cuò)誤,故想記錄下來警醒自己和分享各位。 前端技術(shù)棧是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:對(duì)于程序員來說,更意味著代碼的組織,工作成員之間的協(xié)作方式。我常犯的一個(gè)錯(cuò)誤是直接在或分支上直接,而團(tuán)隊(duì)是不允許這樣做的。 先介紹下背景,博主由運(yùn)營轉(zhuǎn)行前端,入職一個(gè)月,完成了一個(gè)相對(duì)較大的模塊。由于基礎(chǔ)相對(duì)薄弱,犯下了不少錯(cuò)誤,故想記錄下來警醒自己和分享各位。 前端技術(shù)棧是 ES6 + backbone + react + antdUI,后端使用的 Ruby on Rails。 1....
摘要:原文出自本文總結(jié)了程序員常犯的個(gè)錯(cuò)誤??梢钥纯礊槭裁丛谥斜辉O(shè)計(jì)成不可變父類和子類的構(gòu)造函數(shù)以上這段代碼出現(xiàn)編譯錯(cuò)誤,因?yàn)槟J(rèn)的父類構(gòu)造函數(shù)未定義。如果程序員定義構(gòu)造函數(shù),編譯器將不插入默認(rèn)的無參數(shù)構(gòu)造函數(shù)。 原文出自:http://www.programcreek.com/2014/05/top-10-mistakes-java-developers-make/ 本文總結(jié)了J...
閱讀 2239·2021-11-19 09:55
閱讀 2726·2021-11-11 16:55
閱讀 3254·2021-09-28 09:36
閱讀 2036·2021-09-22 16:05
閱讀 3389·2019-08-30 15:53
閱讀 1854·2019-08-30 15:44
閱讀 2973·2019-08-29 13:10
閱讀 1408·2019-08-29 12:30