Questa confusione si verificherebbe in situazioni in cui ci sono intese conflittuali di equals
.
compareTo
è "facile" in quanto pone una semplice domanda "quale è più grande?" Se ti è stata data una serie di Cose , come li ordinerai?
equals
d'altra parte vuole chiedere "sono la stessa cosa?"
BigDecimal in Java è uno di questi posti dove ci sono intese conflittuali su cosa significa avere due cose uguali.
BigDecimal foo = new BigDecimal("1.00");
BigDecimal bar = new BigDecimal("1.000");
Queste due entrate avranno lo stesso significato per l'ordinamento. Tuttavia, essi sono non uguali per quanto riguarda l'uguaglianza. Hanno uno stato sottostante diverso (la precisione del numero) e ciò significa che non sono uguali ma foo.compareTo(bar)
restituirà 0.
Considera questo, se per qualche motivo avevi un Map qux = HashMap<BigDecimal, Object>()
, vuoi qux.put(foo,foo)
per prendere lo stesso punto di qux.put(bar,bar)
e quindi sfrattare l'inserimento precedente?
Quindi, mentre sono matematici uguali (che è il modo in cui CompareTo li ordina), non sono lo stato interno uguale, e quindi la necessità dell'incoerenza qui.
Sì, questa incoerenza arriva al prezzo di un carico cognitivo più alto per trattare con BigDecimal. Significa che le mappe potrebbero non comportarsi come vuoi tu ... e la domanda è "quale mappa vuoi comportarti correttamente?"
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.TreeMap;
class Main {
public static void main (String[] args) {
BigDecimal foo = new BigDecimal("1.00");
BigDecimal bar = new BigDecimal("1.000");
HashMap<BigDecimal, String> hash = new HashMap();
TreeMap<BigDecimal, String> tree = new TreeMap();
hash.put(foo, "foo");
hash.put(bar, "bar");
tree.put(foo, "foo");
tree.put(bar, "bar");
System.out.println("hash foo: " + hash.get(foo));
System.out.println("hash bar: " + hash.get(bar));
System.out.println("tree foo: " + tree.get(foo));
System.out.println("tree bar: " + tree.get(bar));
}
}
ideone
Output:
hash foo: foo
hash bar: bar
tree foo: bar
tree bar: bar
Poiché compareTo
ha restituito 0, nella TreeMap, bar
rimosso foo
quando è stata inserita la barra. Tuttavia, poiché si tratta di oggetti diversi con diversi stati interni e quindi diversi codici hash, entrambi erano in grado di esistere all'interno di una HashMap.
Dai documenti :
Note: care should be exercised if BigDecimal
objects are used as keys in a SortedMap or elements in a SortedSet since BigDecimal
's natural ordering is inconsistent with equals. See Comparable, SortedMap or SortedSet for more information.
E così, questo è il problema, l'incoerenza e il "non c'è una buona risposta a questo" dilemma.
Si potrebbe anche immaginare questo con una classe Rational in cui si vuole mantenere 2/4
con lo stato interno di 2/4
in modo che:
Rational twoFourths = new Rational(2,4);
Rational oneHalf = new Rational(1,2);
System.out.println(twoFourths); // prints 2/4
System.out.println(oneHalf); // prints 1/2
System.out.println(twoFourths.compareTo(oneHalf)); // prints 0
System.out.println(twoFourths.equals(oneHalf)); // ???
E tu sei di nuovo contro la stessa domanda. Sono uguali al senso matematico dell'uguaglianza (il che significa che l'hashCode deve anche restituire lo stesso valore?) O non sono uguali usando lo stato orientato agli oggetti del senso di uguaglianza dell'oggetto nonostante sia lo 'stesso'.