java8 - Malentendido acerca del comparador en java 8
order list stream java 8 (1)
public class Test {
public static void main(String[] args) {
List<Pair<String, Integer>> list = new ArrayList<>();
list.add(new Pair<>("1", 8));
list.add(new Pair<>("3", 2));
list.add(new Pair<>("2", 15));
list.stream()
.sorted(Comparator.comparingInt(p -> p.v))
.map(p -> p.k)
.forEach(System.out::println);
}
}
class Pair<K, V> {
K k;
V v;
public Pair(K k, V v) {
this.k = k;
this.v = v;
}
}
Ok, como has entendido, este código imprime las claves de mi par desde el valor más bajo asociado al más alto, así obtengo el resultado esperado:
3 1 2
Hasta aquí todo bien. Ahora que quería hacer lo contrario, pensé que solo tendría que hacer
list.stream()
.sorted(Comparator.comparingInt(p -> p.v).reversed())
.map(p -> p.k)
.forEach(System.out::println);
Pero obtengo un error de compilación:
v cannot be resolved or is not a field
Por lo tanto, parece que comparingInt
devuelve un Comparator<Object>
. ¿Por qué es así? ¿No debería devolver un Comparator<Integer>
?
Ambos son reproducibles con Eclipse Luna versión 1 y javac.
javac -version => 1.8.0
java -version => java version "1.8.0_25"
También puede cambiar el título de mi pregunta si la encuentra demasiado general, pero no pude encontrar los términos correctos.
Creo que es solo que la inferencia de tipo está fallando, básicamente, porque la llamada reverse()
interfiere con el tipo de argumento esperado de sorted()
y la expresión lambda.
Puede hacerlo si especifica el tipo para comparingInt
explícitamente:
list.stream()
.sorted(Comparator.<Pair<String, Integer>>comparingInt(p -> p.v).reversed())
.map(p -> p.k)
.forEach(System.out::println);
O si solo declaras al comparador primero:
Comparator<Pair<String, Integer>> forward = Comparator.comparingInt(p -> p.v);
list.stream()
.sorted(forward.reversed())
.map(p -> p.k)
.forEach(System.out::println);
Me parece que debería haber un Stream.reverseSorted
así que haz que este tipo de cosas sea realmente fácil, pero no parece que exista :(