Java 8 람다, Function.identity () 또는 t-> t

Function.identity()방법 의 사용법에 관한 질문이 있습니다 .

다음 코드를 상상해보십시오.

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.

당신이 사용해야하는 이유 어떤 이유가 Function.identity()대신 str->str(또는 그 반대). 나는 두 번째 옵션이 더 읽기 쉽다고 생각합니다 (물론 맛). 그러나 선호해야하는 “진정한”이유가 있습니까?



답변

현재 JRE 구현 시점에서 Function.identity()항상 동일한 인스턴스를 반환하지만 각 발생은 identifier -> identifier자체 인스턴스를 생성 할뿐만 아니라 고유 한 구현 클래스를 갖습니다. 자세한 내용은 여기를 참조 하십시오 .

그 이유는 컴파일러 (의 경우, 람다 식의 사소한 본체 들고 합성법 생성한다는 것이다 x->x같음, return identifier;)이 메소드를 호출하는 기능 인터페이스의 구현을 생성하는 런타임 말한다. 따라서 런타임은 다른 대상 메소드 만 볼 수 있으며 현재 구현에서는 메소드를 분석하여 특정 메소드가 동일한 지 여부를 확인하지 않습니다.

따라서 Function.identity()대신에 사용 x -> x하면 메모리가 절약 될 수 있지만 실제로 x -> x보다 읽기 쉽다고 생각하면 결정을 내릴 수 없습니다 Function.identity().

디버그 정보가 활성화 된 상태에서 컴파일 할 때 합성 메서드에는 람다식이 포함 된 소스 코드 라인을 가리키는 라인 디버그 속성이 있으므로 Function디버깅하는 동안 특정 인스턴스 의 소스를 찾을 수 있습니다 . 반대로, Function.identity()작업을 디버깅하는 동안 반환 된 인스턴스가 발생하면 누가 해당 메서드를 호출하고 인스턴스를 작업에 전달했는지 알 수 없습니다.


답변

당신의 예에서 사이에 큰 차이가 없다 str -> str그리고 Function.identity()그것은 단순히 내부 보낸 사람 t->t.

그러나 때로는 사용할 수 Function.identity없기 때문에 사용할 수 없습니다 Function. 여기를보세요 :

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

이것은 잘 컴파일됩니다

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

하지만 컴파일하려고하면

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

mapToInt예상치 ToIntFunction않은 컴파일 오류가 발생 하는데 이는 관련이 없습니다 Function. 또한 방법 ToIntFunction이 없습니다 identity().


답변

로부터 JDK 소스 :

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

문법적으로 올바른 한, 아닙니다.


답변