programing

Java 8 비교기 유형 추론에 매우 혼란스럽다.

randomtip 2022. 9. 4. 13:01
반응형

Java 8 비교기 유형 추론에 매우 혼란스럽다.

난 그 차이점에 대해 알아봤어Collections.sort ★★★★★★★★★★★★★★★★★」list.sort, 「」의 에 「」를 참조해 주세요.Comparator정적 방법 및 람다 식에 매개 변수 유형이 필요한지 여부를 나타냅니다.에 예를 레퍼런스를 할 수 Song::getTitle문제를 해결하기 위해서입니다만, 여기서의 질문은 수정하고 싶은 것이 아니라, 왜 Java 컴파일러가 이 문제를 처리하는지에 대한 답변입니다.

이게 제 소견입니다. '우리'가 칩시다.ArrayList입입 of Song 몇 , 세 가지 표준 방법이 즉, ㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴ)입니다.

    ArrayList<Song> playlist1 = new ArrayList<Song>();

    //add some new Song objects
    playlist.addSong( new Song("Only Girl (In The World)", 235, "Rhianna") );
    playlist.addSong( new Song("Thinking of Me", 206, "Olly Murs") );
    playlist.addSong( new Song("Raise Your Glass", 202,"P!nk") );

다음으로 동작하는 두 가지 유형의 정렬 메서드에 대한 호출을 나타냅니다.

Collections.sort(playlist1, 
            Comparator.comparing(p1 -> p1.getTitle()));

playlist1.sort(
            Comparator.comparing(p1 -> p1.getTitle()));

을 하자마자 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★」thenComparing하다

Collections.sort(playlist1,
            Comparator.comparing(p1 -> p1.getTitle())
            .thenComparing(p1 -> p1.getDuration())
            .thenComparing(p1 -> p1.getArtist())
            );

playlist1.sort(
        Comparator.comparing(p1 -> p1.getTitle())
        .thenComparing(p1 -> p1.getDuration())
        .thenComparing(p1 -> p1.getArtist())
        );

, 문, 문, 음, 음의 를 모르기 에 구문 가 발생합니다.p1그래서 이렇게 유형.Song(비교의 첫 에 대해서: (비교는 과 같습니다.

Collections.sort(playlist1,
            Comparator.comparing((Song p1) -> p1.getTitle())
            .thenComparing(p1 -> p1.getDuration())
            .thenComparing(p1 -> p1.getArtist())
            );

playlist1.sort(
        Comparator.comparing((Song p1) -> p1.getTitle())
        .thenComparing(p1 -> p1.getDuration())
        .thenComparing(p1 -> p1.getArtist())
        );

이제 혼란스러운 부분이 나옵니다.pp 의 경 pp의 laylist1.sort 두 오류를 모두 thenComparing 단, 콜.의 경우Collections.sort첫 번째 문제에서는 해결되지만 마지막 문제에서는 해결되지 않습니다.에서는, 콜을 더 했습니다.thenComparing, 마지막에는 '오류'를 안 돼요.(Song p1)파라미터를 지정합니다.

.TreeSet and and and를 Objects.compare:

int x = Objects.compare(t1, t2, 
                Comparator.comparing((Song p1) -> p1.getTitle())
                .thenComparing(p1 -> p1.getDuration())
                .thenComparing(p1 -> p1.getArtist())
                );


    Set<Song> set = new TreeSet<Song>(
            Comparator.comparing((Song p1) -> p1.getTitle())
            .thenComparing(p1 -> p1.getDuration())
            .thenComparing(p1 -> p1.getArtist())
            );

TreeSet컴파일 오류는 없습니다.Objects.compare의 콜thenComparing을 사용하다

, 왜 '이러다', '이러다', '이러다', '이러다', '이러다', '이러다', '이러다', '이러다', '이러다', '이러다', '이러다', '이러다'를 사용할 가 없는 ?(Song p1)메서드를 더 이상 (더 이상)는 없습니다)thenComparing콜)을 클릭합니다.

의 같은 으로, 이 으로 이 을 할 때 입니다.TreeSet:

Set<Song> set = new TreeSet<Song>(
            Comparator.comparing(p1 -> p1.getTitle())
            .thenComparing(p1 -> p1.getDuration())
            .thenComparing(p1 -> p1.getArtist())
            );

즉, 활자를 제거합니다.Song의 첫 콜 아래의 구문 와 첫 의 lamda가 표시됩니다.thenComparing, 최종 않습니다.thenComparing ! - 와는 정반대! '3번으로 하다' 입니다.Objects.compare,List.sort ★★★★★★★★★★★★★★★★★」Collections.sort 첫 번째를 했을 때Song 구문 를 표시합니다.param type은 모든 콜의 구문 오류를 .

미리 감사 드려요.

Eclipse Kepler SR2에서 받은 에러의 스크린샷을 포함하도록 편집되었으며, 명령줄에서 JDK8 Java 컴파일러를 사용하여 컴파일하면 정상으로 컴파일되기 때문에 그 이후로는 Eclipse 고유하다는 것을 알게 되었습니다.

이클립스의 정렬 오류

우선, 원인 에러의 모든 예는, 참조 실장(JDK 8의 javac)으로 올바르게 컴파일 됩니다.인텔리J에서도 정상적으로 동작하고 있기 때문에, 이클립스 고유의 에러일 가능성이 있습니다.

당신의 근본적인 질문은 "체인을 시작하면 왜 작동이 중지되는가?" 입니다.그 이유는 람다 식과 일반 메서드 호출이 메서드 매개 변수로 표시될 때는 폴리 식이지만(그 유형은 컨텍스트에 따라 다름), 메서드 수신기 식으로 표시될 때는 그렇지 않기 때문입니다.

당신이 말할 때

Collections.sort(playlist1, comparing(p1 -> p1.getTitle()));

유형 인수 양쪽에 대해 해결하기에 충분한 유형 정보가 있다.comparing()및 인수 유형p1.그comparing()콜의 타겟유형은 시그니처로부터 취득됩니다.Collections.sort그래서 알려져 있다.comparing()a를 반환해야 합니다.Comparator<Song>, 따라서p1야 한다.Song.

하지만 체인을 시작하면:

Collections.sort(playlist1,
                 comparing(p1 -> p1.getTitle())
                     .thenComparing(p1 -> p1.getDuration())
                     .thenComparing(p1 -> p1.getArtist()));

이제 문제가 생겼네우리는 복합 표현이comparing(...).thenComparing(...)은 「」입니다.Comparator<Song>은 ", " " 입니다.comparing(p -> p.getTitle())는 일반적인 메서드 호출입니다.다른 인수에서 타입 파라미터를 추론할 수 없습니다.운은 별로 없습니다.을 모르기 에 이 에 '어느 정도인지', '어느 정도인지', '어느 정도인지', '어느 정도인지 '어느 정도인지', '어느 정도인지', '어느 정도인지', '어느 정도인지'를 알 수 없어요.thenComparing방법 등

이를 수정하는 방법에는 여러 가지가 있는데, 이 모든 방법에는 체인의 첫 번째 오브젝트가 올바르게 입력될 수 있도록 더 많은 타입 정보를 주입하는 것이 포함됩니다.다음은 만족도가 감소하고 간섭도가 증가하는 대략적인 순서입니다.

  • 「과부하 없는 방법」과 , 참조없는 를합니다.Song::getTitle '다 하다', '다 하다', '다 하다'의 유형 할 수 있는 유형 를 얻을 수 있습니다comparing()호출하고 타입을 지정하여 체인을 계속합니다.
  • 예제에서와 같이 명시적인 람다를 사용합니다.
  • .comparing() ★★★★★★★★★★★★★★Comparator.<Song, String>comparing(...)
  • 합니다.Comparator<Song>

문제는 타입 회의입니다.「」를 하지 않고,(Song s)비교는 '''로 하겠습니다'''는comparator.comparing오브젝트

이 문제는 다음 3가지 방법 중 하나로 해결할 수 있습니다.

  1. 새로운 Java 8 메서드 참조 구문 사용

     Collections.sort(playlist,
                Comparator.comparing(Song::getTitle)
                .thenComparing(Song::getDuration)
                .thenComparing(Song::getArtist)
                );
    
  2. 각 비교 단계를 로컬 참조로 끌어냅니다.

      Comparator<Song> byName = (s1, s2) -> s1.getArtist().compareTo(s2.getArtist());
    
      Comparator<Song> byDuration = (s1, s2) -> Integer.compare(s1.getDuration(), s2.getDuration());
    
        Collections.sort(playlist,
                byName
                .thenComparing(byDuration)
                );
    

    편집

  3. Comparator에서 반환되는 유형 강제 적용(입력 유형과 비교 키 유형 모두 필요)

    sort(
      Comparator.<Song, String>comparing((s) -> s.getTitle())
                .thenComparing(p1 -> p1.getDuration())
                .thenComparing(p1 -> p1.getArtist())
                );
    

마지막은 '마지막'이라고 합니다.thenComparing구문 오류가 잘못 전달되었습니다.실제로는 체인 전체의 타입 문제입니다.컴파일러가 체인의 끝을 구문 오류로 표시했을 뿐입니다.그때 최종 반환 타입이 일치하지 않는 것 같습니다.

그런지List는, 보다 .Collection같은 타입의 캡처가 가능하지만, 확실히 그렇지 않은 것 같습니다.

이 컴파일 시간 오류를 해결하는 다른 방법은 다음과 같습니다.

첫 번째 비교 함수의 변수를 명시적으로 캐스팅한 다음 바로 사용할 수 있습니다.org.bson 목록을 정리했습니다.Documents 객체.샘플 코드를 봐주세요.

Comparator<Document> comparator = Comparator.comparing((Document hist) -> (String) hist.get("orderLineStatus"), reverseOrder())
                       .thenComparing(hist -> (Date) hist.get("promisedShipDate"))
                       .thenComparing(hist -> (Date) hist.get("lastShipDate"));
list = list.stream().sorted(comparator).collect(Collectors.toList());

playlist1.sort(...)플레이리스트1의 EEEEEEElist1 。이 선언은 비교기에 "리플링"됩니다.

»Collections.sort(...), 첫 하지 않습니다

'' 은 ' 행동을 할 수 것 요.Collections.<Song>sort(...) 테스트하기 8 는 없습니다.

언급URL : https://stackoverflow.com/questions/24436871/very-confused-by-java-8-comparator-type-inference

반응형