Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Misunderstanding about Comparator in java 8

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, as you understood this code is printing my pair keys from the lowest value associated to the highest so I get the expected output:

3 1 2

So far so good. Now I wanted to do the reverse, I thought I would only have to do

list.stream()
    .sorted(Comparator.comparingInt(p -> p.v).reversed())
    .map(p -> p.k)
    .forEach(System.out::println);

But I get a compilation error:

v cannot be resolved or is not a field

So it seems like comparingInt is returning a Comparator<Object>. Why it so? Shouldn't it return a Comparator<Integer> ?

These are both reproductible with Eclipse Luna version 1 and javac.

javac -version => 1.8.0
java  -version => java version "1.8.0_25"

Oh also feel free to change the title of my question is you find it too general, but I couldn't find the correct terms

like image 772
user2336315 Avatar asked Nov 29 '14 18:11

user2336315


1 Answers

I believe it's just that type inference is failing, basically - because the reverse() call gets in the way of the expected argument type of sorted() and the lambda expression.

You can do it if you specify the type to comparingInt explicitly:

list.stream()
    .sorted(Comparator.<Pair<String, Integer>>comparingInt(p -> p.v).reversed())
    .map(p -> p.k)
    .forEach(System.out::println);

Or if you just declare the comparer first:

Comparator<Pair<String, Integer>> forward = Comparator.comparingInt(p -> p.v);
list.stream()
    .sorted(forward.reversed())
    .map(p -> p.k)
    .forEach(System.out::println);

It feels to me like there should be a Stream.reverseSorted so make this sort of thing really easy, but it doesn't look like it exists :(

like image 75
Jon Skeet Avatar answered Sep 29 '22 01:09

Jon Skeet