En mi opinión, no hay un par en Java porque, si desea agregar funcionalidad adicional directamente en el par (por ejemplo, comparable), debe vincular los tipos. En C ++, simplemente no nos importa, y si los tipos que componen un par no tienen operator <
, el pair::operator <
no se compilará también.
Un ejemplo de Comparable sin límite:
public class Pair<F, S> implements Comparable<Pair<? extends F, ? extends S>> {
public final F first;
public final S second;
/* ... */
public int compareTo(Pair<? extends F, ? extends S> that) {
int cf = compare(first, that.first);
return cf == 0 ? compare(second, that.second) : cf;
}
//Why null is decided to be less than everything?
private static int compare(Object l, Object r) {
if (l == null) {
return r == null ? 0 : -1;
} else {
return r == null ? 1 : ((Comparable) (l)).compareTo(r);
}
}
}
/* ... */
Pair<Thread, HashMap<String, Integer>> a = /* ... */;
Pair<Thread, HashMap<String, Integer>> b = /* ... */;
//Runtime error here instead of compile error!
System.out.println(a.compareTo(b));
Un ejemplo de Comparable con la verificación en tiempo de compilación para determinar si los argumentos de tipo son comparables:
public class Pair<
F extends Comparable<? super F>,
S extends Comparable<? super S>
> implements Comparable<Pair<? extends F, ? extends S>> {
public final F first;
public final S second;
/* ... */
public int compareTo(Pair<? extends F, ? extends S> that) {
int cf = compare(first, that.first);
return cf == 0 ? compare(second, that.second) : cf;
}
//Why null is decided to be less than everything?
private static <
T extends Comparable<? super T>
> int compare(T l, T r) {
if (l == null) {
return r == null ? 0 : -1;
} else {
return r == null ? 1 : l.compareTo(r);
}
}
}
/* ... */
//Will not compile because Thread is not Comparable<? super Thread>
Pair<Thread, HashMap<String, Integer>> a = /* ... */;
Pair<Thread, HashMap<String, Integer>> b = /* ... */;
System.out.println(a.compareTo(b));
Esto es bueno, pero esta vez no puede usar tipos no comparables como argumentos de tipo en Par. Uno puede usar muchos comparadores para pares en alguna clase de utilidad, pero las personas de C ++ pueden no obtenerlo. Otra forma es escribir muchas clases en una jerarquía de tipos con diferentes límites en los argumentos de tipo, pero hay demasiados límites posibles y sus combinaciones ...
AbstractMap.SimpleEntry
complicado?