Java 8 lambdas, Function.identity() o t-> t
function t r (3)
A partir de la implementación actual de JRE,
Function.identity()
siempre devolverá la misma instancia, mientras que cada aparición de
identifier -> identifier
no solo creará su propia instancia, sino que incluso tendrá una clase de implementación distinta.
Para más detalles, ver
here
.
La razón es que el compilador genera un método sintético que contiene el cuerpo trivial de esa expresión lambda (en el caso de
x->x
, equivalente al
return identifier;
) y le dice al tiempo de ejecución que cree una implementación de la interfaz funcional que llama a este método.
Por lo tanto, el tiempo de ejecución solo ve diferentes métodos de destino y la implementación actual no analiza los métodos para averiguar si ciertos métodos son equivalentes.
Por lo tanto, usar
Function.identity()
lugar de
x -> x
podría ahorrar algo de memoria, pero eso no debería impulsar su decisión si realmente cree que
x -> x
es más legible que
Function.identity()
.
También puede considerar que al compilar con la información de depuración habilitada, el método sintético tendrá un atributo de depuración de línea que apunta a la (s) línea (s) del código fuente que contiene la expresión lambda, por lo tanto, tiene la posibilidad de encontrar el origen de una instancia de
Function
particular mientras depuración
Por el contrario, al encontrar la instancia devuelta por
Function.identity()
durante la depuración de una operación, no sabrá quién llamó a ese método y pasó la instancia a la operación.
Tengo una pregunta sobre el uso del método
Function.identity()
.
Imagine el siguiente código:
Arrays.asList("a", "b", "c")
.stream()
.map(Function.identity()) // <- This,
.map(str -> str) // <- is the same as this.
.collect(Collectors.toMap(
Function.identity(), // <-- And this,
str -> str)); // <-- is the same as this.
¿Hay alguna razón por la que deba usar
Function.identity()
lugar de
str->str
(o viceversa).
Creo que la segunda opción es más legible (una cuestión de gustos, por supuesto).
Pero, ¿hay alguna razón "real" por la que uno debería ser preferido?
De la fuente JDK :
static <T> Function<T, T> identity() {
return t -> t;
}
Entonces, no, siempre que sea sintácticamente correcto.
En su ejemplo, no hay una gran diferencia entre
str -> str
y
Function.identity()
ya que internamente es simplemente
t->t
.
Pero a veces no podemos usar
Function.identity
porque no podemos usar una
Function
.
Echa un vistazo aquí:
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
esto compilará bien
int[] arrayOK = list.stream().mapToInt(i -> i).toArray();
pero si intentas compilar
int[] arrayProblem = list.stream().mapToInt(Function.identity()).toArray();
obtendrá un error de compilación ya que
mapToInt
espera
ToIntFunction
, que no está relacionado con
Function
.
Además,
ToIntFunction
no tiene el método de
identity()
.