2016-09-12 7 views
-2

ich ein TreeMap wie diese erstellt haben:Java TreeMap null zurück für Schlüssel, wenn der Wert existiert

Map<Date, List<MyInput>> inputsByDate = new TreeMap<>(new Comparator<Date>() { 
     @Override 
     public int compare(Date lhs, Date rhs) { 
      return dateUtil.compareDay(lhs, rhs); 
     } 


    }); 

im Komparator Meine Methode ist nicht schön, aber zumindest identifiziert Ähnlichkeit (ich verwende HashMap nicht mit equals und Hash aus anderen Gründen):

public int compareDay(Date lhs, Date rhs) { 
    Calendar cal1 = Calendar.getInstance(); 
    Calendar cal2 = Calendar.getInstance(); 
    cal1.setTime(lhs); 
    cal2.setTime(rhs); 
    boolean sameDay = cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && 
      cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR); 
    if (sameDay) { 
     return 0; 
    } else { 
     return -1; 
    } 
} 

Wie auch immer, das Problem ist das folgende Schnipsel. Das letzte Element ist null, wenn ich es abrufe.

public List<MyType> convert(Map<Date, List<MyInput>> inputByDate, Map<Date, Boolean> isDoneByDate) { 
     List<MyType> result = Lists.newArrayList(); 
     for (Date dateKey : inputByDate.keySet()) { 
      boolean isDone = false; 
      Boolean res = isDoneByDate.get(dateKey); 
      if (res != null) { 
       isDone = res; 
      } 
      List<MyInput> inputs = inputByDate.get(dateKey); 

      MyType retrieved=new MyType(dateKey, inputs, isDone); 
      result.add(retrieved); 
     } 
     return result; 
    } 

Als ich den letzten Schnipsel mit dem Debugger ausführen ich deutlich, dass es sehen ist (als Beispiel) 3 Schlüssel mit Werten, die nicht null sind. Ich muss hier etwas vermissen, weil ich nicht sehen kann, wie Berichte null sein können, wenn ich validiert habe, dass jedem Schlüssel zuvor ein gültiges Paar zugeordnet wurde. Jede Hilfe würde sehr geschätzt werden.

+0

Der Komparator muss <, ==, > ermitteln, nicht nur == und! =. Das ist negativ 0 oder positiver Rückgabewert. Überprüfen Sie die Dokumentation für Komparatoren. -1 bedeutet lhs

+0

Btw, meinst du 'inputByDate.keySet()' anstelle von 'inputByDate()'? Und was ist 'reportsByDay'? – Thomas

+0

Meine schlechte, meine "Verschleierung", die ich auf meinen tatsächlichen Code angewendet habe, war fehlerhaft. Jetzt korrigiert. –

Antwort

3

Wenn die Daten unterschiedlich Ihre Vergleicher sind, sollten -1 zurück oder 1, da sie symmetrisch sein muss, das heißt, wenn Sie -1 zurück, wenn date1 zu vergleichen und date2 Sie haben 1 zurück, wenn date2 und date1 zu vergleichen. Ihr Code ist verpflichtet, die Karte zu brechen, da er eine Reihenfolge für die Schlüssel nicht zuverlässig bestimmen kann.

So Ihre compare() zu so etwas wie dieses Refactoring:

int result = Integer.compare(cal1.get(Calendar.YEAR), cal2.get(Calendar.YEAR)); 
if(result == 0) { //if the year is equal compare the days 
    result = Integer.compare(cal1.get(Calendar.DAY_OF_YEAR), cal2.get(Calendar.DAY_OF_YEAR)); 
} 
return result; 

Edit: Eine kleine Panne auf, was wahrscheinlich mit Ihrem Komparator passiert ist.

Wenn Sie sich die Quellen ansehen, sehen Sie, dass die Karte den neuen Schlüssel mit den bereits vorhandenen Schlüsseln vergleicht. Ihr Vergleicher würde sie somit gemäß der Einfügereihenfolge ordnen, d. H. Da Sie immer -1 für ungleiche Schlüssel zurückgeben, folgt die Karte immer dem linken Zweig, und somit ist das zuletzt hinzugefügte Element das "kleinste". Das ist aber nur ein weiteres Problem.

Das Problem, dem Sie gegenüberstehen, ist in der getEntryUsingComparator() Methode zu finden, die indirekt von get(key) aufgerufen wird. Das Verfahren sieht wie folgt aus:

Comparator<? super K> cpr = comparator; 
if (cpr != null) { 
    Entry<K,V> p = root; 
    while (p != null) { 
    int cmp = cpr.compare(k, p.key); 
    if (cmp < 0) 
     p = p.left; 
    else if (cmp > 0) 
     p = p.right; 
    else 
     return p; 
    } 
} 
return null; 

Wie Sie aufgrund immer wiederkehr sehen -1 das Verfahren immer den cmp < 0 Zweig bis p = p.left Ergebnisse in p = null ausführen würde, weil es nicht mehr linkes Element ist, und dann wird die while-Schleife beendet und du landest bei return null;.

+0

Ich war mir bewusst, dass der Komparator nicht symmetrisch ist, aber ich dachte "Scheiß drauf, ich werde sowieso nie mehr als 10 Schlüssel in dieser Karte haben.". Das war ein schlechter Schachzug, denn jetzt funktioniert es. –

+0

@why_vincent froh zu hören, dass es jetzt funktioniert. – Thomas

Verwandte Themen