Streamクラスのソート方法


StreamのソートとComparatorの比較Int


streamクラスのソート方法とComparatorの比較Intコードを深く学び、stream、generic、lambdaを学ぶことができます.
 

表示するセクション

  • Streamの分類方法
  • Stream<T> sorted(Comparator<? super T> comparator);
  • Comparatorの比較Intメソッド
  • public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
    }
  • Comparator Functional Interface
  • @FunctionalInterface
    public interface Comparator<T> {
    
        int compare(T o1, T o2);
        boolean equals(Object obj);
        ~~~
    }
     

    サンプルコード


    2つの方法で簡単な例を作成しましょう.
    ドリンク類でドリンクリストを作成しております価格の昇順に飲み物のリストを並べます.
    public class GenericWildCardExample {
        public static void main(String[] args) {
            List<Beverage> beverages = Arrays.asList(new Beverage(3000), new Beverage(2000), new Beverage(10000), new Beverage(4000));
    
            List<Beverage> sortedBeverages = beverages.stream().sorted(Comparator.comparingInt(Beverage::getPrice))
                .collect(toList());
    
            for (Beverage sortedBeverage : sortedBeverages) {
                System.out.println("sortedBeverage.getPrice() = " + sortedBeverage.getPrice());
            }
        }
    }
    
    class Beverage{
        private int price;
    
        public Beverage(int price) {
            this.price = price;
        }
    
        public int getPrice() {
            return price;
        }
    }
    결과 출력
    sortedBeverage.getPrice() = 2000
    sortedBeverage.getPrice() = 3000
    sortedBeverage.getPrice() = 4000
    sortedBeverage.getPrice() = 10000
     

    アクセスコード


    まず、Streamのソート()を表示します.ソート方法のパラメータを表示している場合、Comparatorcomparator.つまり、GenericタイプのTまたはT親としてComparatorのパラメータを受信しています.
    Stream<T> sorted(Comparator<? super T> comparator);
    (이 코드가 어렵다면 Generic - WildCard를 공부해보세요)
     
    Comparatorを見てみましょう.
    @FunctionalInterface
    public interface Comparator<T> {
    
        int compare(T o1, T o2);
        boolean equals(Object obj);
        
        ~~~
    }
    Comparatorは関数インタフェースです.このコードを読んだとき、疑問がありました.
    関数型インタフェースにはなぜ2つの抽象的な方法があるのか...?
    ここでequalsは実際にObjectクラスのメソッドである.したがって,Comparatorインタフェースの抽象的な方法はcomparareである.
    注)https://stackoverflow.com/questions/23721759/functionalinterface-comparator-has-2-abstract-methods
     
    本題に戻る.
    ソート・メソッドのパラメータはComparator、Comparatorは関数インタフェースであるため、ソート・メソッドのパラメータは次のとおりです.
    (To 1,To 2)->「returninta」形式のram式.
    では、サンプルコードでは、Comparatorはソート中です.CompareIntはどのようにソートパラメータに入りますか?
    List<Beverage> sortedBeverages = beverages.stream().sorted(Comparator.comparingInt(Beverage::getPrice))
                .collect(toList());
    Comparator.CompareIntの戻り形式を表示し、その理由を確認します.
        public static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
            Objects.requireNonNull(keyExtractor);
            return (Comparator<T> & Serializable)
                (c1, c2) -> Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
        }
    Int表示戻り値(c 1,c 2)->returnint}形式のram式を比較します.
    では、IntのパラメータToInteFunctionを比較するとどうなるのでしょうか.
    IntのパラメータToIntFutionを比較してみましょう.
    @FunctionalInterface
    public interface ToIntFunction<T> {
    
        /**
         * Applies this function to the given argument.
         *
         * @param value the function argument
         * @return the function result
         */
        int applyAsInt(T value);
    }
    ToIntoFunctionは関数インタフェースであり、パラメータを受信してintを返す抽象的な方法を有する.
    したがって、サンプルコードのcompareningInt()は、パラメータ(c 1,c 2)->returnint}形式のram式としてgetPrice()を使用するパラメータ形式で最適な方法を得る.
    次に、sorded()は、比較Intが返すram式をパラメータとして比較してストリームをソートする.
    List<Beverage> sortedBeverages = beverages.stream().sorted(Comparator.comparingInt(Beverage::getPrice))
                .collect(toList());

    もっと知りたい


    なぜ
  • ComparingIntがラムダ式に戻るときにComparator&Serializableを貼り付けるのですか?
  • シリアル化
  • Streamのソート方法はどこにあり、内部でどのように動作していますか?