java - Why does this program using Collections.sort only fail for lists of size 32 or more? -


the following program throws following exception:

java.lang.illegalargumentexception: comparison method violates general contract! 

i understand problem comparator. see unable replicate : "comparison method violates general contract!"

i don't understand why fails lists of size 32 or more. can explain?

class experiment {      private static final class myinteger {         private final integer num;          myinteger(integer num) {             this.num = num;         }     }      private static final comparator<myinteger> comparator = (r1, r2) -> {         if (r1.num == null || r2.num == null)             return 0;         return integer.compare(r1.num, r2.num);     };      public static void main(string[] args) {         myinteger[] array = {new myinteger(0), new myinteger(1), new myinteger(null)};         random random = new random();         (int length = 0;; length++) {             (int attempt = 0; attempt < 100000; attempt++) {                 list<myinteger> list = new arraylist<>();                 int[] arr = new int[length];                 (int k = 0; k < length; k++) {                     int rand = random.nextint(3);                     arr[k] = rand;                     list.add(array[rand]);                 }                 try {                     collections.sort(list, comparator);                 } catch (exception e) {                     system.out.println(arr.length + " " + arrays.tostring(arr));                     return;                 }             }         }     } } 

it depends on implementation, in openjdk 8 size of array checked against min_merge, equal 32. avoids call mergelo/mergehi throw exception.

from jdk / jdk / openjdk / 7u40-b43 8-b132 7-b147 - 8-b132 / java.util.timsort:

static <t> void sort(t[] a, int lo, int hi, comparator<? super t> c,                      t[] work, int workbase, int worklen) {     assert c != null && != null && lo >= 0 && lo <= hi && hi <= a.length;      int nremaining  = hi - lo;     if (nremaining < 2)         return;  // arrays of size 0 , 1 sorted      // if array small, "mini-timsort" no merges     if (nremaining < min_merge) {         int initrunlen = countrunandmakeascending(a, lo, hi, c);         binarysort(a, lo, hi, lo + initrunlen, c);         return;     }      /**      * march on array once, left right, finding natural runs,      * extending short natural runs minrun elements, , merging runs      * maintain stack invariant.      */     timsort<t> ts = new timsort<>(a, c, work, workbase, worklen);     int minrun = minrunlength(nremaining);     {         // identify next run         int runlen = countrunandmakeascending(a, lo, hi, c);          // if run short, extend min(minrun, nremaining)         if (runlen < minrun) {             int force = nremaining <= minrun ? nremaining : minrun;             binarysort(a, lo, lo + force, lo + runlen, c);             runlen = force;         }          // push run onto pending-run stack, , maybe merge         ts.pushrun(lo, runlen);         ts.mergecollapse();          // advance find next run         lo += runlen;         nremaining -= runlen;     } while (nremaining != 0);      // merge remaining runs complete sort     assert lo == hi;     ts.mergeforcecollapse();     assert ts.stacksize == 1; } 

Comments

Popular posts from this blog

asp.net mvc - SSO between MVCForum and Umbraco7 -

Python Tkinter keyboard using bind -

ubuntu - Selenium Node Not Connecting to Hub, Not Opening Port -