Java 8 스트림의 .min () 및 .max () : 왜 컴파일됩니까?
참고 :이 질문은 이전 SO 질문 인 데드 링크에서 비롯되었지만 여기에 있습니다 ...
이 코드를 참조하십시오 ( 참고 :이 코드는 "작동하지 않는다"는 것을 알고 Integer::compare
있어야합니다. 링크 된 질문에서 추출했습니다 .
final ArrayList <Integer> list
= IntStream.rangeClosed(1, 20).boxed().collect(Collectors.toList());
System.out.println(list.stream().max(Integer::max).get());
System.out.println(list.stream().min(Integer::min).get());
.min()
및 의 javadoc에 따르면 .max()
둘 다의 인수는이어야합니다 Comparator
. 그러나 여기에서 메소드 참조는 Integer
클래스의 정적 메소드에 대한 것 입니다.
그렇다면 왜 이것이 전혀 컴파일되지 않습니까?
명확하지 않기 때문에 여기서 일어나는 일을 설명하겠습니다!
먼저 스트림의 항목을 서로 비교하여 너무 걱정할 필요가없는 최적의 순서로 최소 또는 최대를 찾을 수 있도록 Stream.max()
인스턴스를 허용합니다 Comparator
.
물론 문제는 왜 Integer::max
받아 들여 집니까? 결국 그것은 비교기가 아닙니다!
새로운 람다 기능이 Java 8에서 작동하는 방식이 정답입니다. 이는 "단일 추상 메소드"인터페이스 또는 "SAM"인터페이스로 알려진 개념에 의존합니다. 아이디어는 하나의 추상 메소드가있는 인터페이스는 메소드 서명이 인터페이스의 한 메소드와 일치하는 람다 (또는 메소드 참조)에 의해 자동으로 구현 될 수 있다는 것입니다. 따라서 Comparator
인터페이스 (단순 버전)를 검사하십시오 .
public Comparator<T> {
T compare(T o1, T o2);
}
메소드가를 찾고 있다면 Comparator<Integer>
본질적으로이 서명을 찾고있는 것입니다.
int xxx(Integer o1, Integer o2);
메소드 이름이 일치 목적으로 사용되지 않기 때문에 "xxx"를 사용합니다 .
따라서, 모두 Integer.min(int a, int b)
와 Integer.max(int a, int b)
오토 박싱이은으로 표시 할 수 있음을 충분히 가까이있는 Comparator<Integer>
방법의 맥락에서가.
Comparator
는 기능적 인터페이스 이며 Integer::max
해당 인터페이스를 준수합니다 (자동 박스 / 언 박스를 고려한 후). 두 개의 int
값을 가져 와서 int
-를 기대하는 것처럼 Comparator<Integer>
(Integer / int 차이를 무시하기 위해 가늘게 뜨고)를 반환합니다 .
그러나 Integer.max
의 의미 를 준수하지 않는 한 올바른 일을 기대 하지는 않습니다 Comparator.compare
. 실제로 실제로는 실제로 작동하지 않습니다. 예를 들어, 하나의 작은 변경을 수행하십시오.
for (int i = 1; i <= 20; i++)
list.add(-i);
... 이제 max
값은 -20이고 min
값은 -1입니다.
대신 두 통화 모두 다음을 사용해야합니다 Integer::compare
.
System.out.println(list.stream().max(Integer::compare).get());
System.out.println(list.stream().min(Integer::compare).get());
이것은 인터페이스 Integer::min
의 구현으로 해석 되기 때문에 작동 합니다 Comparator<Integer>
.
에 대한 Integer::min
해결 Integer.min(int a, int b)
, 참조 IntBinaryOperator
및 아마도 오토 박싱에 대한 메소드 참조는 어딘가에서 발생합니다 BinaryOperator<Integer>
.
그리고 min()
resp max()
메소드 Stream<Integer>
는 Comparator<Integer>
인터페이스를 구현 하도록 요청합니다 .
이제 이것은 단일 방법으로 해결됩니다 Integer compareTo(Integer o1, Integer o2)
. 어떤 유형 BinaryOperator<Integer>
입니다.
따라서 마술은 두 방법이 모두 그렇듯이 일어났습니다 BinaryOperator<Integer>
.
David M. Lloyd가 제공 한 정보 외에도이를 허용하는 메커니즘을 대상 타이핑 이라고 합니다.
컴파일러가 람다 식 또는 메서드 참조에 할당하는 형식은 식 자체뿐만 아니라 사용되는 위치에 따라 달라집니다.
표현식의 대상은 결과가 지정된 변수 또는 결과가 전달되는 매개 변수입니다.
Lambda expressions and method references are assigned a type which matches the type of their target, if such a type can be found.
See the Type Inference section in the Java Tutorial for more information.
I had an error with an array getting the max and the min so my solution was:
int max = Arrays.stream(arrayWithInts).max().getAsInt();
int min = Arrays.stream(arrayWithInts).min().getAsInt();
참고URL : https://stackoverflow.com/questions/22561614/java-8-streams-min-and-max-why-does-this-compile
'Programing' 카테고리의 다른 글
ASP.NET MVC 응용 프로그램 성능을 개선하려면 어떻게합니까? (0) | 2020.04.30 |
---|---|
루트 액세스없이 파이썬 모듈을 설치하는 방법은 무엇입니까? (0) | 2020.04.30 |
dyld : 라이브러리가로드되지 않았습니다… 이유 : 이미지를 찾을 수 없습니다 (0) | 2020.04.30 |
AngularJS에서 HTTP 'Get'서비스 응답을 캐시 하시겠습니까? (0) | 2020.04.30 |
직렬화 할 수없는 작업 : 객체가 아닌 클래스에서만 클로저 외부에서 함수를 호출 할 때 java.io.NotSerializableException (0) | 2020.04.30 |