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()
.