Что такое практическое использование метода java.util.function.Function.identity?

Почему я должен использовать Function.identity(), когда он возвращает ту же самую вещь, которую он получает, ничего не делая с помощью ввода или каким-либо образом модифицируя вход?

Apple apple = new Apple(10, "green");
Function<Apple, Apple> identity = Function.identity();
identity.apply(apple);

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

Ответы

Ответ 1

Предполагаемое использование - это когда вы используете метод, который принимает Function для сопоставления чего-либо, и вам необходимо сопоставить вход непосредственно с выходом функции (функция "identity").

Как очень простой пример, сопоставление списка лиц с картой от имени к человеку:

import static java.util.function.Function.identity

// [...]

List<Person> persons = ...
Map<String, Person> = persons.stream()
        .collect(Collectors.toMap(Person::name, identity()))

Функция identity() предназначена только для удобства и удобочитаемости. Как указывает Питер в своем ответе, вы можете просто использовать t → t, но лично я считаю, что использование identity() лучше передает намерения, поскольку не оставляет места для интерпретации, как интересно, забыл ли оригинальный автор сделать трансформацию в этой лямбда. Я признаю, что это очень субъективно и предполагает, что читатель знает, что такое identity().

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

Ответ 2

Например, вы можете использовать его для подсчета частоты.

public static <T> Map<T, Long> frequencyCount(Collection<T> words) {
    return words.stream()
            .collect(Collectors.groupingBy(Function.identity(),
                    Collectors.counting());
}

В этом случае вы говорите, что ключ для группы - это элемент в коллекции (без его преобразования).

Лично я нахожу это более кратким

import static java.util.stream.Collectors.*;

public static Map<String, Long> frequencyCount(Collection<String> words) {
    return words.stream()
            .collect(groupingBy(t -> t,
                    counting());
}

Ответ 3

Предположим, что у вас есть List<String> strings = List.of("abc", "de") и вы хотите сгенерировать Map где Key - это форма значения, что List и Value is length:

 Map<String, Integer> map = strings.stream() 
        .collect(Collectors.toMap(Function.identity(), String::length)) 

Обычно некоторые люди видят Function.identity() немного менее читаемыми, чем t → t например, но, как объяснено здесь, это немного отличается.