Comparator 사용 상세 및 일부 코드 분석

11916 단어 자바
최근 에 Comparator 를 많이 써 서 재 미 있 고 간단 하고 쓰기 편 해 요.기록 하기;
1.소개
Comparator 안의 방법 은 우 리 는 몇 가지 유형 으로 나 눌 수 있다.아래 의 테스트 코드 도 이 몇 가지 유형 에 따라 그 중의 일부 방법 을 테스트 하고 나머지 방법 은 유사 하 므 로 사용 하지 않 습 니 다.
  • compare-정상 비교
  • naturalOrder-자연 비교,실체 류 에 따라 정 의 된 Comparable
  • nullsFirst,nullsLast-null 값 을 첫 번 째 또는 마지막 에 두 기
  • comparing,comparingLong,comparingInt,comparingDouble-상용 비교 방법 으로 매개 변수 유형
  • 을 지정 할 수 있 습 니 다.
  • reversed,reverseOrder-반전
  • thenComparing,thenComparing Double,thenComparingInt,thenComparingLong-여러 번 비교
  •   comparing        thenComparing,       
    

    2.테스트
    package com.study.testCompare;
    
    import org.junit.Test;
    
    import java.math.BigDecimal;
    import java.util.*;
    
    public class ComparatorTest {
    
        @Test
        public void testCompare() {
            List personList = new ArrayList<>();
            personList.add(new Person("a", new BigDecimal(12), 170));
            personList.add(new Person("b", new BigDecimal(24), 175, new Student(27)));
            personList.add(new Person("c", new BigDecimal(12), 177));
            personList.add(new Person("a", new BigDecimal(12), 177));
            personList.add(new Person("b", new BigDecimal(54), 174, new Student(19)));
    
            // naturalOrder
            System.out.println("naturalOrder : ");
            personList.sort(Comparator.naturalOrder());
            personList.forEach(System.out::println);
    
            // comparing 1.0
            Optional optional = personList.stream().max(Comparator.comparing(Person::getAge));
            System.out.println("comparing 1.0 : get max age " + optional.get().toString() + "
    "); // comparing 2.1 optional = personList.stream().max(Comparator.comparing(Person::getName, Comparator.reverseOrder())); System.out.println("comparing 2.1 : get min name " + optional.get().toString() + "
    "); // comparing 2.2 optional = personList.stream().max(Comparator.comparing(Person::getName, String::compareTo)); System.out.println("comparing 2.2 : get max name " + optional.get().toString() + "
    "); // comparing 2.3 optional = personList.stream().max(Comparator.comparing(Person::getStudent, (o1, o2) -> new Student().compare(o1, o2))); System.out.println("comparing 2.3 : get max student.age " + optional.get().toString() + "
    "); // thenComparing 1.0 System.out.println("thenComparing 1.0 : "); personList.sort(Comparator.comparing(Person::getAge).thenComparing(Person::getHeight)); personList.forEach(System.out::println); // thenComparing 2.0 System.out.println("thenComparing 2.0 : "); personList.sort(Comparator.comparing(Person::getAge).thenComparing(Person::getHeight).thenComparing(Person::getName)); personList.forEach(System.out::println); // System.out.println(" : "); personList.sort(Comparator.comparingInt(Person::getHeight)); personList.forEach(System.out::println); // System.out.println(" : "); personList.sort(Comparator.comparingInt(Person::getHeight).reversed()); personList.forEach(System.out::println); // nullsLast System.out.println("nullsLast : "); personList.sort(Comparator.nullsLast(Comparator.comparing(Person::getName))); personList.forEach(System.out::println); // nullsLast System.out.println("nullsLast : "); personList.sort(Comparator.nullsLast(Comparator.comparing(Person::getName))); personList.forEach(System.out::println); } }
    package com.study.testCompare;
    
    import lombok.Data;
    
    import java.math.BigDecimal;
    import java.util.Comparator;
    
    @Data
    public class Person implements Comparable {
        private String name;
        private BigDecimal age;
        private Integer height;
        private Student student;
    
        public Person(String name, BigDecimal age, Integer height) {
            this.name = name;
            this.age = age;
            this.height = height;
            this.student = new Student(0);
        }
    
        public Person(String name, BigDecimal age, Integer height, Student student) {
            this.name = name;
            this.age = age;
            this.height = height;
            this.student = student;
        }
    
        @Override
        public int compareTo(Object o) {
            Person p1 = (Person) o;
    
            if (this.age.equals(p1.age)) {
                return p1.height - this.height;
            }
           return this.age.compareTo(p1.age);
        }
    }
    
    @Data
    class Student implements Comparator {
    
        private int age;
    
        public Student() {
        }
    
        public Student(int age) {
            this.age = age;
        }
    
        @Override
        public int compare(Object o1, Object o2) {
    
            Student p1 = (Student) o1;
            Student p2 = (Student) o2;
    
            int result = Integer.compare(p1.age, p2.age);
    
            result = result == 0 ? ((p1.age > p2.age) ? 1 : -1) : result;
    
            return result;
        }
    }
    
    

    3.소스 코드
    
    package java.util;
    
    import java.io.Serializable;
    import java.util.function.Function;
    import java.util.function.ToIntFunction;
    import java.util.function.ToLongFunction;
    import java.util.function.ToDoubleFunction;
    import java.util.Comparators;
    
    /**
     *     ,    
     */
    @FunctionalInterface
    public interface Comparator {
        /**
         *        
         * o1 = o2 : return 0;
         * o1 > o2 : return 1;
         * o1 < o2 : return -1;
         */
        int compare(T o1, T o2);
    
        /**
         * equals   
         */
        boolean equals(Object obj);
    
        /**
         *     
         */
        default Comparator reversed() {
            return Collections.reverseOrder(this);
        }
    
        /**
         *      ,           ,         ,         
         * @since 1.8
         */
        default Comparator thenComparing(Comparator super T> other) {
            Objects.requireNonNull(other);
            return (Comparator & Serializable) (c1, c2) -> {
                int res = compare(c1, c2);
                return (res != 0) ? res : other.compare(c1, c2);
            };
        }
    
        /**
         *      ,    ,   compara
         * @since 1.8
         */
        default  Comparator thenComparing(
                Function super T, ? extends U> keyExtractor,
                Comparator super U> keyComparator)
        {
            return thenComparing(comparing(keyExtractor, keyComparator));
        }
    
        /**
         *      ,    
         * @since 1.8
         */
        default > Comparator thenComparing(
                Function super T, ? extends U> keyExtractor)
        {
            return thenComparing(comparing(keyExtractor));
        }
    
        /**
         *      ,  Int  
         * @since 1.8
         */
        default Comparator thenComparingInt(ToIntFunction super T> keyExtractor) {
            return thenComparing(comparingInt(keyExtractor));
        }
    
        /**
         *      ,  Long  
         * @since 1.8
         */
        default Comparator thenComparingLong(ToLongFunction super T> keyExtractor) {
            return thenComparing(comparingLong(keyExtractor));
        }
    
        /**
         *      ,  Double  
         * @since 1.8
         */
        default Comparator thenComparingDouble(ToDoubleFunction super T> keyExtractor) {
            return thenComparing(comparingDouble(keyExtractor));
        }
    
        /**
         *     
         * @since 1.8
         */
        public static > Comparator reverseOrder() {
            return Collections.reverseOrder();
        }
    
        /**
         *     (        Comparable)
         * @since 1.8
         */
        @SuppressWarnings("unchecked")
        public static > Comparator naturalOrder() {
            return (Comparator) Comparators.NaturalOrderComparator.INSTANCE;
        }
    
        /**
         *       ,     
         * @since 1.8
         */
        public static  Comparator nullsFirst(Comparator super T> comparator) {
            return new Comparators.NullComparator<>(true, comparator);
        }
    
        /**
         *        ,      
         * @since 1.8
         */
        public static  Comparator nullsLast(Comparator super T> comparator) {
            return new Comparators.NullComparator<>(false, comparator);
        }
    
        /**
         *     (  ,    Comparator),      。    Comparator
         * @since 1.8
         */
        public static  Comparator comparing(
                Function super T, ? extends U> keyExtractor,
                Comparator super U> keyComparator)
        {
            Objects.requireNonNull(keyExtractor);
            Objects.requireNonNull(keyComparator);
            return (Comparator & Serializable)
                (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                                  keyExtractor.apply(c2));
        }
    
        /**
         *     (  ,    Comparator)。    
         * @since 1.8
         */
        public static > Comparator comparing(
                Function super T, ? extends U> keyExtractor)
        {
            Objects.requireNonNull(keyExtractor);
            return (Comparator & Serializable)
                (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
        }
    
        /**
         *      —— int
         * @since 1.8
         */
        public static  Comparator comparingInt(ToIntFunction super T> keyExtractor) {
            Objects.requireNonNull(keyExtractor);
            return (Comparator & Serializable)
                (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
        }
    
        /**
         *      —— long
         * @since 1.8
         */
        public static  Comparator comparingLong(ToLongFunction super T> keyExtractor) {
            Objects.requireNonNull(keyExtractor);
            return (Comparator & Serializable)
                (c1, c2) -> Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
        }
    
        /**
         * *      —— double
         * @since 1.8
         */
        public static Comparator comparingDouble(ToDoubleFunction super T> keyExtractor) {
            Objects.requireNonNull(keyExtractor);
            return (Comparator & Serializable)
                (c1, c2) -> Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
        }
    }
    
    

    4.부분 해석 방법
    원본 코드:
        /**
         *     (  ,    Comparator)。    
         * @since 1.8
         */
        public static > Comparator comparing(
                Function super T, ? extends U> keyExtractor)
        {
            Objects.requireNonNull(keyExtractor);
            return (Comparator & Serializable)
                (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
        }
    
    

    사용:
            // comparing 1.0
            Optional optional = personList.stream().max(Comparator.comparing(Person::getAge));
            System.out.println("comparing 1.0 : max age " + optional.get().toString() + "
    ");

    debug 를 통 해 알 수 있 듯 이 최종 소스 코드c1c2는 Person 대상 이 고 비교 할 때 IntegercompareTo를 호출 했다.그럼 알 수 있 습 니 다keyExtractor.apply(c1) = c1.getAge(),keyExtractor.apply(c2) = c2.getAge().그리고 소스 코드 에서 명확 하 게 지적 했다.Function super T, ? extends U> keyExtractor그 중에서:
  • T입력 유형
  • U반환 유형 이기 때문에 우 리 는 lamble 을 사용 한 후에 들 어 온PersonT이 고getAgeU이다.그래서keyExtractor.apply돌아 온 것 은Integer유형의age이다.최종 적 으로 대응 하 는 포장 유형compareTo을 호출 하여 비교
  • 좋은 웹페이지 즐겨찾기