2017-02-08 10 views
2

Я пытаюсь написать следующий код:Тип вывод порвал с беглым API

Map<String, String> m = new HashMap<>(); 
// ... populate the map 
m.entrySet().stream() 
     .sorted(Comparator.comparing(e -> e.getKey()).reversed()) 
     .forEach(System.out::println); 

Это не компилируется, потому что выведенный тип для e является Object. Однако, если я удаляю вызов .reversed(), это делает вывод. Я должен изложить тип для e, который некрасиво:

 .sorted(Comparator.comparing((Map.Entry<String, String> e) -> e.getKey()).reversed()) 

компилятор может определить тип для Comparator.comparing, но когда я добавляю reversed(), она не может. Зачем?

ответ

0

статический метод используется здесь

Comparator.comparing() 

является универсальным методом, но не указать здесь, что он принимает в качестве аргумента, и то, что он возвращается - это должно быть указано где-то.

Мое предложение небольшое изменение, заменив литья e на Map.Entry, которые потенциально могли бы выглядеть лучше

Map<String, String> m = new HashMap<>(); 
// ... populate the map 
m.entrySet().stream() 
     .sorted(Comparator.<Map.Entry<String, String>, String>comparing(Map.Entry::getKey).reversed()) 
     .forEach(System.out::println); 
+0

Обычно, Java выводит аргументы типа. Но после добавления 'reverse()', мне нужно явно их записать. Зачем? – Oliv

+0

Я сделал несколько тестов, и когда у вас есть код без 'reverse()', 'Map.Entry :: getKey' разрешен как' (stringStringEntry) -> stringStringEntry.getKey() ', но в случае, если вы его отменили , тот же 'Map.Entry :: getKey' разрешен как' (Функция ) (t) -> Map.Entry.getKey (t) ', что явно неверно, так как теперь мы бы также возвращали' Comparator '' как неопределенный тип 'U' и неправильный метод getKey', поскольку он принимает' t' в качестве параметра и вызывается классом Map.Entry. Очень интересно, но все же непонятно для меня. – amalgamat

1

This answer объясняет, почему он не компилируется.

У вас есть несколько способов исправить код:

//cheat a bit 
.sorted(Entry.comparingByKey(Comparator.reverseOrder())) 

//provide the target type 
.sorted(Entry.<String, String> comparingByKey().reversed()) 

//explicitly give the type of e 
.sorted(Comparator.comparing((Entry<String, String> e) -> e.getKey()).reversed()) 
+0

Это два альтернативных решения. Но ни один из них не столь изящный, как интуитивный оригинальный. На самом деле, я разрабатываю API, который страдает от той же проблемы, что и метод 'sorted()'. Интересно, могу ли я что-то изменить в API, чтобы упростить простую версию. – Oliv

+0

@Oliv Я не думаю, что они менее элегантные, просто разные - однако я согласен с вами в том, что фактический ответ должен будет объяснить, почему ваше решение не работает. – Deltharis

+0

Я имею в виду, менее элегантный, чем '.sorted (Comparator.comparing (e -> e.getKey()). reverseed()) 'или даже' .sorted (Comparator.comparing (Entry :: getKey) .reversed()) ' – Oliv