質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1135閲覧

thenComparingによってlong[] の 第一要素、第二要素の順でソートしたい

ruei

総合スコア284

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2020/04/07 20:35

編集2020/04/07 20:38

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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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
xebme

総合スコア1090

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

xebme

2020/04/12 09:24 編集

結論を追記しました。 最後に、配列のサイズに合わせたComparator<long[]>を追記しました。 有益な質問でした。ありがとうございます。
swordone

2020/04/12 11:44

個人的にラッパークラスを使っているのが嫌なので、ラッパークラスを避けて書いてみました。 IntFunction<Comparator<long[]>> genComparatorChain = size -> IntStream.range(0,size).mapToObj(i -> Comparator.comparingLong((long[] x) -> x[i]) .reduce((a, b) -> 0, Comparator::thenComparing);
xebme

2020/04/13 10:03

ありがとうございます。Comparatorの動作が1回多くなるのが課題です。
guest

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

hoshi-takanori

総合スコア7901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

swordone

2020/04/08 00:20

でも実際それしかないんですよね。 あと型間違えています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問