programing

Java 8 스트림의 .min() 및 .max(): 컴파일 이유는 무엇입니까?

nicescript 2022. 10. 10. 18:43
반응형

Java 8 스트림의 .min() 및 .max(): 컴파일 이유는 무엇입니까?

주의: 이 질문은 이전 SO 질문이었던 데드링크에서 비롯되었습니다만, 다음 질문입니다.

이 코드를 참조해 주세요(주의: 이 코드는 「작동」하지 않고, 사용할 필요가 있습니다.링크된 질문에서 추출한 것입니다).

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

및 의 javadoc에 따르면 양쪽 인수는Comparator여기서 메서드 참조는 클래스의 정적 메서드에 대한 것입니다.

그럼 이게 왜 컴파일 되는 거죠?

여기서 무슨 일이 일어나고 있는지 설명해줄게, 왜냐하면 그건 명백하지 않거든!

첫 번째로 스트림 내의 아이템을 서로 비교하여 최소 또는 최대를 찾을 수 있도록의 인스턴스를 받아들입니다.이것에 대해서는, 그다지 걱정할 필요가 없는 최적의 순서로 지정합니다.

그래서 질문은 당연히 왜 받아들여지는가 하는 것입니다.결국 비교기가 아니었군!

정답은 Java 8에서 새로운 람다 기능이 작동하는 방식입니다.이것은 비공식적으로 "단일 추상적 방법" 인터페이스 또는 "SAM" 인터페이스로 알려진 개념에 의존합니다.하나의 추상적인 메서드를 가진 인터페이스는 모두 람다(또는 메서드 참조)에 의해 자동으로 구현될 수 있으며 메서드 시그니처는 인터페이스 상의 단일 메서드와 일치합니다.이 때문에, 인터페이스(단순한 버전)를 조사합니다.

public Comparator<T> {
    T compare(T o1, T o2);
}

메서드가 다음을 찾는 경우Comparator<Integer>그럼 기본적으로 다음 시그니처를 찾습니다.

int xxx(Integer o1, Integer o2);

method name은 매칭 목적으로 사용되지 않기 때문에 "xxx"를 사용합니다.

따라서 둘 다Integer.min(int a, int b)그리고.Integer.max(int a, int b)자동 박스를 사용하면, 이 기능을 1대 1로 표시할 수 있습니다.Comparator<Integer>메서드 컨텍스트에서.

Comparator기능하는 인터페이스입니다.Integer::max는, 그 인터페이스에 준거하고 있습니다(자동 박스화/언박스를 고려한 후).두 개면 된다int값을 매겨 반환한다.int- 예상대로Comparator<Integer>to(정수/int 차이를 무시하기 위해 눈을 가늘게 뜨고 있습니다).

하지만, 나는 그것이 옳은 일을 할 것이라고 기대하지 않는다.Integer.max의미에 준거하지 않는다Comparator.compare그리고 실제로 일반적으로는 효과가 없습니다.예를 들어, 작은 변경을 1개 실시합니다.

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()반응max()의 메서드Stream<Integer>에게 묻다Comparator<Integer>구현되는 인터페이스.
이제 이 문제는 단일 방법으로 해결됩니다.Integer compareTo(Integer o1, Integer o2)어떤 종류입니까?BinaryOperator<Integer>.

그래서 마법은 두 가지 방법 모두 하나의 방법이기 때문에 일어났다.BinaryOperator<Integer>.

데이비드 M이 알려준 정보 말고는요Lloyd one은 이것을 가능하게 하는 메커니즘을 target typing이라고 덧붙일 수 있다.

컴파일러가 람다 표현식이나 메서드 참조에 할당하는 타입은 표현식 자체뿐만 아니라 사용되는 위치에 따라 달라집니다.

식의 대상은 결과가 할당되는 변수 또는 결과가 전달되는 매개 변수입니다.

람다 식과 방법 참조에는 대상 유형과 일치하는 유형이 할당됩니다(찾을 수 있는 경우).

자세한 내용은 Java 튜토리얼의 "유형 추론" 섹션을 참조하십시오.

어레이가 최대값과 최소값을 얻는 동안 오류가 발생했기 때문에 해결 방법은 다음과 같습니다.

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

반응형