Lambdas de Java 8, Function.identity() o t->t

Resuelto asked hace 9 años • 0 respuestas

Tengo una pregunta sobre el uso del Function.identity()método.

Imagina 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 deberías usar Function.identity()en lugar de str->str(o viceversa)? Creo que la segunda opción es más legible (cuestión de gustos, claro). Pero, ¿existe alguna razón "real" por la que se debería preferir uno?

 avatar Jan 20 '15 03:01
Aceptado

A partir de la implementación actual de JRE, Function.identity()siempre devolverá la misma instancia, mientras que cada aparición de identifier -> identifierno solo creará su propia instancia sino que incluso tendrá una clase de implementación distinta. Para obtener más detalles, consulte aquí .

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 a return identifier;) y le indica al motor 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 descubrir si ciertos métodos son equivalentes.

Por lo tanto, usar Function.identity()en lugar de x -> xpodría ahorrar algo de memoria, pero eso no debería influir en su decisión si realmente cree que x -> xes 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 las líneas del código fuente que contienen la expresión lambda, por lo tanto, tiene la posibilidad de encontrar la fuente de una Functioninstancia particular durante la depuración. . Por el contrario, cuando encuentre la instancia devuelta 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.

Holger avatar Jan 20 '2015 09:01 Holger

En tu ejemplo no hay gran diferencia entre str -> stry Function.identity()ya que internamente es simplemente t->t.

Pero a veces no podemos usarlo Function.identityporque no podemos usar un archivo Function. Échale un vistazo aquí:

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);

esto se 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 mapToIntse espera ToIntFunction, que no está relacionado con Function. Tampoco ToIntFunctiontiene identity()método.

Pshemo avatar Jan 19 '2015 20:01 Pshemo

De la fuente JDK :

static <T> Function<T, T> identity() {
    return t -> t;
}

Entonces no, siempre y cuando sea sintácticamente correcto.

JasonN avatar Jan 19 '2015 20:01 JasonN