2016-06-20 37 views
4

由Joshua Bloch和尼爾Gafter爲什麼這種用Java 1.8

import java.util.*; 

public class BananaBread { 
    public static void main(String[] args) { 
     Integer[] array = { 3, 1, 4, 1, 5, 9 }; 
     Arrays.sort(array, new Comparator<Integer>() { 
      public int compare(Integer i1, Integer i2) { 
       return i1 < i2 ? -1 : (i2 > i1 ? 1 : 0); 
      } 
     }); 
     System.out.println(Arrays.toString(array)); 
    } 
} 

預期的行爲是不確定的,文中說,它返回從Java謎題兩者[3,1,4,1,5, 9]。在Java 1.7版本中這是真實的。但是,在Java版本1.8中,輸出是排序列表。

我可以看到Timsort在Java 1.8中是新的,但我不確定該算法如何用不一致的比較器(如上面給出的那樣)運行。任何幫助或深入瞭解如何可以將不勝感激。

+0

自動裝箱問題?我寧願使用'Integer'中的'compareTo'。 –

+0

這是在這個問題相同的代碼:http://stackoverflow.com/questions/8900871/unexpected-output-using-comparator。不包括新的Java 8排序。 – Tunaki

+1

i1 < i2 vs. i2 > i1 .... hmmm ....... ;-)我不認爲「Undefined」意味着「Java必須對每個Java版本都做同樣的事情」。 –

回答

7

Java 8使用修改的合併排序。它使用的關鍵線路

// From TimSort.binarySort 
while (left < right) { 
    int mid = (left + right) >>> 1; 
    if (c.compare(pivot, a[mid]) < 0) // compares for less than 0. 
     right = mid; 
    else 
     left = mid + 1; 
} 

注:只在乎你是否返回-1或0(更具體地說是< 0,true或false)

你比較相同

return i1 < i2 ? -1 : 0; 

因此,在所有對此代碼都很重要的方面它是正確的。

注意:如果你改變這樣

return i1 > i2 ? +1 : 0; 

代碼它不排序任何東西。

+2

如果使用VM arg'-Djava.util.Arrays.useLegacyMergeSort = true',則可以獲得原始合併排序。有人懶惰地編碼我們的比較器做-1和0,並且我永遠花了我的時間來弄清楚爲什麼當我們遷移到JDK8時它停止排序。 – Compass