thenComparingを用いて長さ2の配列の集合を第一要素、第二要素の優先度順でソートしたいと考えています。
具体的には
Java
1Arrays.sort(a, new Comparator<int[]>() { 2 @Override 3 public int compare(long[] o1, long[] o2) { 4 if(o1[0]!=o2[0]) return Long.compare(o1[0], o2[0]); 5 else return Long.compare(o1[1], o2[1]); 6 } 7});
と同じ働きをするコードを書きたいです。
第一要素によるソートは
Java
1Arrays.sort(a, Comparator.comparing(v->v[0]));
とすることで行うことが出来ることを手元で確かめています。
しかし、第二要素による比較を入れた
Java
1Arrays.sort(a, Comparator.comparing(v->v[0]).thenComparing(v->v[1]));
ですと、Exception in thread "main" java.lang.Error: Unresolved compilation problem:
というエラーが発生してしまいます。修正方法の分かる方ご教示ください。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
とりあえず。
Java
1import java.util.ArrayList; 2import java.util.Arrays; 3import java.util.Comparator; 4import java.util.List; 5import java.util.function.BiFunction; 6import java.util.function.Consumer; 7import java.util.function.Function; 8import java.util.stream.Collectors; 9import java.util.stream.IntStream; 10 11public class Sorters { 12 13 static Comparator<long[]> comparator1 = Comparator.comparing(v -> v[0] * Integer.MAX_VALUE + v[1]); 14 static Comparator<long[]> comparator2 = Comparator.comparing((long[] v) -> v[0]).thenComparing(v -> v[1]); 15 static Comparator<long[]> comparator3 = Comparator.<long[], Long>comparing(v -> v[0]).thenComparing(v -> v[1]); 16 static Comparator<long[]> comparator4 = Comparator.<long[], Long>comparing(v -> v[0]).thenComparingLong(v -> v[1]); 17 18 static Function<Integer,Function<long[],Long>> getElement = i -> (array) -> array[i]; 19 static Comparator<long[]> comparator13 = Comparator.comparing(getElement.apply(0)).thenComparing(getElement.apply(1)); 20 21 static Comparator<long[]> comparator12 = (x,y) -> 22 IntStream.range(0, Math.min(x.length,y.length)) 23 .map(i -> Long.compare(x[i], y[i])) 24 .dropWhile(i -> i == 0) 25 .findFirst() 26 .orElse(0); 27 28 static Function<Integer,Comparator<long[]>> genComparatorChain = size -> 29 IntStream.range(0,size) 30 .mapToObj(i -> Comparator.<long[],Long>comparing(x -> x[i])) 31 .reduce((a,b) -> 0, Comparator::thenComparing); 32 static Comparator<long[]> comparator14 = genComparatorChain.apply(2); 33 34 static BiFunction<Comparator<long[]>, long[][], long[][]> sorter = 35 (comparator, array) -> Arrays.stream(array) 36 .sorted(comparator) 37 .collect(Collectors.toList()) 38 .toArray(new long[0][0]); 39 40 static Consumer<long[][]> dump_ = 41 array -> { 42 Arrays.stream(array).map(Arrays::toString).forEach(System.out::println); 43 System.out.println(); 44 }; 45 46 public static void main(String[] args) { 47 long[][] a = { { 1, 3 }, { 2, 3 }, { 1, 2 }, { 9, 1 }, { 0, 9 }, { 0, 4 }}; 48 49 dump_.accept(sorter.apply(comparator1,a)); 50 dump_.accept(sorter.apply(comparator2,a)); 51 dump_.accept(sorter.apply(comparator3,a)); 52 dump_.accept(sorter.apply(comparator4,a)); 53 dump_.accept(sorter.apply(comparator13,a)); 54 dump_.accept(sorter.apply(comparator12,a)); 55 dump_.accept(sorter.apply(comparator14,a)); 56 } 57}
結論(追記)
thenComparing
のkyExtractorの型が推論されない問題の解決として、以下の3つの方法がありました。
- Comparator.comparingに指定するラムダ式の、引数に型
long[]
を指定する - staticメソッドComparator.comparingにkeyExtractorの型
<long[], Long>
を指定する - あらかじめkeyExtractor関数
Function<long[],Long>
を定義しておき渡す。
Java
1// 1 2Comparator.comparing((long[] v) -> v[0]).thenComparing(v -> v[1]); 3// 2 4Comparator.<long[], Long>comparing(v -> v[0]).thenComparing(v -> v[1]); 5// 3 6Function<Integer,Function<long[],Long>> getElement = i -> (array) -> array[i]; 7Comparator<long[]> comparator13 = Comparator.comparing(getElement.apply(0)).thenComparing(getElement.apply(1));
配列のサイズに合わせたComparator<long[]>(追記)
結論の3番目を変形して、配列のサイズに応じたComparator<long[]>
が作れることがわかりました。
Java
1Function<Integer,Comparator<long[]>> genComparatorChain = size -> 2 IntStream.range(0,size) 3 .mapToObj(i -> Comparator.<long[],Long>comparing(x -> x[i])) 4 .reduce((a,b) -> 0, Comparator::thenComparing); 5Comparator<long[]> comparator14 = genComparatorChain.apply(2);
結論:Comparatorに限らず、Functionインターフェイスでもreduce()を使って、compose()、andThen()をチェインできることがわかり有益でした。
投稿2020/04/08 03:18
編集2020/04/12 09:46総合スコア1090
0
ベストアンサー
v の型を明示したらいけましたけど、負けた気がする…。
java
1import java.util.*; 2 3public class Sorter { 4 public static void main(String[] args) { 5 int[][] a = { 6 {1, 3}, {2, 3}, {1, 2} 7 }; 8 9 //Arrays.sort(a, Comparator.comparing(v->v[0])); 10 //Arrays.sort(a, Comparator.comparing(v -> v[0]).thenComparing(v -> v[1])); 11 Arrays.sort(a, Comparator.comparing((int[] v) -> v[0]).thenComparing(v -> v[1])); 12 13 for (int[] b : a) { 14 System.out.println("{" + b[0] + ", " + b[1] + "}"); 15 } 16 } 17}
投稿2020/04/07 23:25
総合スコア7901
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/04/12 09:24 編集
2020/04/12 11:44
2020/04/13 10:03