Issue
I have one List<List> I want to sort it according to column . I used the following code.
// data is List<List<String>>
data.sort(Comparator.comparing(e-> e.get(col)));
Its working and sorting according column specified. But If I used reversed()
or thenComparing()
method, It says
error: cannot find symbol
data.sort(Comparator.comparing(e-> e.get(col)).reversed() );
^
symbol: method get(int)
location: variable e of type Object
Also with the thenComparing method,
error: cannot find symbol
data.sort(Comparator.comparing(e-> e.get(col)).thenComparing(e->e.get(col2)) );
^
symbol: method get(int)
location: variable e of type Object
error: cannot find symbol
data.sort(Comparator.comparing(e-> e.get(col)).thenComparing(e->e.get(col2)) );
^
symbol: method get(int)
location: variable e of type Object
2 errors
I'm not getting anything from the error messages. Fyi, Im using OpenJDK 11 for this.
Solution
Seems like java doesn't infer the type once you have a second layer.
In the first example.
data.sort( Comparator.comparing( e-> e.get(0) ) );
The type is inferred from data, but in the second example.
data.sort( Comparator.comparing( e-> e.get(0) ).reversed() );
The type of 'comparing' is not inferred. You can resolve this a couple ways, the easiest to be explicit.
data.sort( Comparator.comparing( (List<String> e) -> e.get(0) ).reversed() );
It seems funny that java doesn't chain inferences. If we include the intermediate step of creating the comparator, we can see pretty clearly it doesn't.
Comparator<List<String>> c = Comparator.comparing( e-> e.get(0) ).reversed();
| Error: | cannot find symbol
| symbol: method get(int)
| Comparator<List> c = Comparator.comparing( e->e.get(0) ).reversed();
| ^---^
| Error:
| incompatible types: java.util.Comparator<java.lang.Object> cannot be converted to java.util.Comparator<java.util.List<java.lang.String>>
| Comparator<List> c = Comparator.comparing( e->e.get(0) ).reversed();
| ^--------------------------------------------^
Now we get two errors, one in the lambda because the argument is an Object, and the second error because we're creating a Comparator<Object>.
I'm thinking it works this way, but I'm not sure how to verify. 'reversed' will take the type argument of the instance calling it, the type is not inferred. By the time 'reversed' is called the object has to have been instantiated and the generic assigned. The call to comparing then has no upper bounds, it just has to return a Comparator<?>.
An alternative solution, specify the types when the Comparator is called.
Comparator<List<String>> c = Comparator.<List<String>, String>comparing( e->e.get(0) ).reversed();
Answered By - matt
Answer Checked By - Katrina (JavaFixing Volunteer)