Na minha opinião, não há Par em Java porque, se você deseja adicionar funcionalidade extra diretamente ao par (por exemplo, Comparável), deve vincular os tipos. Em C ++, simplesmente não nos importamos e, se os tipos que compõem um par não tiverem operator <
, opair::operator <
eles também não serão compilados.
Um exemplo de Comparável sem limite:
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));
Um exemplo de Comparável com verificação em tempo de compilação para saber se os argumentos de tipo são comparáveis:
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));
Isso é bom, mas desta vez você não pode usar tipos não comparáveis como argumentos de tipo no par. Pode-se usar muitos Comparadores para Par em alguma classe de utilitário, mas as pessoas em C ++ podem não entender. Outra maneira é escrever muitas classes em uma hierarquia de tipos com limites diferentes nos argumentos de tipo, mas existem muitos limites possíveis e suas combinações ...
AbstractMap.SimpleEntry
complicado?