it-swarm.com.de

Java 8 lambdas, Function.identity () oder t-> t

Ich habe eine Frage zur Verwendung der Function.identity() -Methode.

Stellen Sie sich den folgenden Code vor:

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.

Gibt es einen Grund, warum Sie Function.identity() anstelle von str->str Verwenden sollten (oder umgekehrt)? Ich denke, dass die zweite Option besser lesbar ist (natürlich Geschmackssache). Aber gibt es einen "echten" Grund, warum man bevorzugt werden sollte?

198
user4464654

Ab der aktuellen JRE-Implementierung gibt Function.identity() immer dieselbe Instanz zurück, während jedes Vorkommen von identifier -> identifier Nicht nur eine eigene Instanz erstellt, sondern sogar eine eigene Implementierungsklasse hat. Weitere Einzelheiten finden Sie unter hier .

Der Grund dafür ist, dass der Compiler eine synthetische Methode generiert, die den trivialen Rumpf dieses Lambda-Ausdrucks enthält (im Fall von x->x, Entsprechend return identifier;) Und die Laufzeit anweist, eine Implementierung des Funktionalen zu erstellen Schnittstelle, die diese Methode aufruft. Daher werden zur Laufzeit nur verschiedene Zielmethoden angezeigt, und die aktuelle Implementierung analysiert die Methoden nicht, um festzustellen, ob bestimmte Methoden gleichwertig sind.

Wenn Sie also Function.identity() anstelle von x -> x Verwenden, wird möglicherweise Speicherplatz gespart. Dies sollte jedoch nicht zu Ihrer Entscheidung führen, wenn Sie der Meinung sind, dass x -> x Besser lesbar ist als Function.identity().

Sie können auch in Betracht ziehen, dass beim Kompilieren mit aktivierten Debug-Informationen die synthetische Methode ein Line-Debug-Attribut hat, das auf die Quellcodezeile (n) mit dem Lambda-Ausdruck verweist. Daher haben Sie die Möglichkeit, die Quelle eines bestimmten Function Instanz beim Debuggen. Wenn Sie dagegen beim Debuggen einer Operation auf die von Function.identity() zurückgegebene Instanz stoßen, wissen Sie nicht, wer diese Methode aufgerufen und die Instanz an die Operation übergeben hat.

257
Holger

In Ihrem Beispiel gibt es keinen großen Unterschied zwischen str -> str Und Function.identity(), da es intern einfach t->t Ist.

Aber manchmal können wir Function.identity Nicht verwenden, weil wir kein Function verwenden können. Schauen Sie sich hier um:

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

dies wird gut kompilieren

int[] arrayOK = list.stream().mapToInt(i -> i).toArray();

aber wenn du versuchst zu kompilieren

int[] arrayProblem = list.stream().mapToInt(Function.identity()).toArray();

sie erhalten einen Kompilierungsfehler, da mapToIntToIntFunction erwartet, was nicht mit Function zusammenhängt. Auch ToIntFunction hat keine identity() -Methode.

79
Pshemo

Aus der JDK-Quelle :

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

Also nein, solange es syntaktisch korrekt ist.

39
JasonN