[java] 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값을 가져 와서 inta Comparator<Integer>를 기대하는 것처럼-를 반환합니다 (다시 말하면 정수 / 정수 차이를 무시하기 위해 가늘게 뜨고 있습니다).

그러나 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 표현식 및 메소드 참조에는 해당 유형을 찾을 수있는 경우 대상의 유형과 일치하는 유형이 지정됩니다.

자세한 정보는 Java 학습서 의 유형 유추 섹션 을 참조하십시오.


답변

내 솔루션이 최대와 최소값을 얻는 배열에 오류가 발생했습니다.

int max = Arrays.stream(arrayWithInts).max().getAsInt();
int min = Arrays.stream(arrayWithInts).min().getAsInt();


답변