Выражение ссылки на метод здесь не ожидается, ошибка времени компиляции - PullRequest
1 голос
/ 20 июня 2020

Я использую поток для итерации по списку и хочу собрать его на карте, но получаю ошибку времени компиляции:

Выражение ссылки на метод здесь не ожидается

Вот мой код

List<Person> personList = getPersons();
Map<String, Integer> personAgeMap = personList.stream()
       .collect(Collectors.toMap(Person::getFirstName + "_" + Person::getLastName, Person::getAge));

Я проверил эти ответы:

, но это не то, что я ищу, также я видел метод ссылочный тип.

В данном случае это метод экземпляра типа экземпляра, как я могу иметь экземпляр Person в коллекторах.

какое может быть возможное решение или это даже выполнимо таким образом ?

Ответы [ 3 ]

3 голосов
/ 20 июня 2020

Вы не можете этого сделать, это не имеет смысла:

Collectors.toMap(Person::getFirstName + "_" + Person::getLastName

Нужно понимать, что такое сигнатура метода toMap . Для простоты предположим, что это:

void toMap(Function<? super T,? extends K> keyMapper)

Понимаете? keyMapper - это объект типа Function. Функция принимает ввод (Person) и возвращает вывод (String). Итак, вам нужно предоставить функцию, которая это сделает. Если вы напишете

Person::getFirstName + "_" + Person::getLastName

, то это ... ну, ничего, но, допустим, в худшем случае это может быть String. Потому что вы объединяете 3 вещи с помощью String. Это не функция. Вы хотите создать функцию.

Итак, вы можете сделать это:

Collectors.toMap(new Function<Person, String>() {
   public String apply(Person person) {
      return person.getFirstName() + "_" + person.getLastName();
   }
});

Сокращение для этого:

Collectors.toMap(person -> person.getFirstName() + "_" + person.getLastName()
2 голосов
/ 20 июня 2020

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

Collectors.toMap(
    p -> String.format("%s_%s", p.getFirstName(), p.getLastName()), 
    Person::getAge
)

Оба Person::getFirstName и Person::getLastName являются экземплярами некоторого функционального интерфейса (никогда не String), например Supplier<String> или Function<Person, String>, и оператора + не может быть применено к ним.

Точно так же это не имело бы особого смысла, если бы вы были

Object o = new Object() + new Object();

Немного озадачить

p -> ((Function<Person, String>) Person::getFirstName).apply(p) + "_" + 
     ((Function<Person, String>) Person::getLastName).apply(p)
1 голос
/ 20 июня 2020

Ссылки на методы используются для ссылки на метод в лямбде. Он не вызывает метод, он предоставляет ссылки на лямбда.

Это означает, что вы не можете использовать ссылку на метод так же, как вызываете метод, поэтому Person::getFirstName + "_" + Person::getLastName неверно .

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

List<Person> personList = getPersons();
Map<String, Integer> personAgeMap = personList.stream()
                                      .collect(Collectors.toMap(person -> person.getFirstName() + "_" + person.getLastName(), Person::getAge));

Надеюсь, я вам пригодился.

...