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

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

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

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

Q&A

解決済

1回答

1189閲覧

java 複数条件でList<Map>をStream APIを使ってソートしたい

makoyang

総合スコア20

Java

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

2グッド

1クリップ

投稿2022/10/05 08:22

実現したいこと

掲題の通りなのですが、List<Map<String, String>のリストをMap内の複数のキーの値で比較してソートがしたいです。
ソートに使用するキーは第1キー、第2キー...と複数あります。

色々検索して参考になりそうなパターン
JavaのStreamを使って複数条件でソートする
はあったのですが、このパターンではList<なんらかのクラス>のクラス内のフィールド(複数)を比較してソートしています。
この なんからのクラス を Map<String, String> に置き換えたいだけなのですが、この実装方法がわからず当サイトに質問の流れとなりました。

以下の「実装したいイメージ」にコンパイルも通らないのですが、やりたい実装イメージを記載いたします。

実装したいイメージ

java

1List<Map<String, String>> sortTargetList = new ArrayList<Map<String,String>>(); 2 3Comparator<Map<String, String>> comparator = 4 Comparator.comparing(Map::get("第1キー")).thenComparing(Map::get("第2キー")); 5 6sortTargetList.stream().sorted(comparator);

環境

java環境:
openjdk version "11" 2018-09-25
OpenJDK Runtime Environment 18.9 (build 11+28)
OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)

最後に

根本的な仕組みがわかってないので参考のパターンからの応用が利かないと自覚はしております。
識者の方々、答えをいただけるだけで非常にありがたいのですが、仕組みも若干説明いただけると更にありがたいです。
よろしくお願いします。

TN8001, takezoux2👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

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

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

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

guest

回答1

0

ベストアンサー

comparingthenComparingの引数keyExtractorは、ソートキーを取り出す関数を指定します。
Comparator#comparing (Java Platform SE 8 )
Comparator#thenComparing (Java Platform SE 8 )

Map<String, String>を受け取ってStringを返す、staticメソッドを作ってしまうのがわかりやすいかもしれません(元ネタと同じくメソッド参照にできます)

ラムダで指定もできますが、チェーンするとエラーになったりしてちょっと注意が必要です。
Comparatorで学ぶJavaのラムダ式 - Qiita
Stream処理における、型推論されない原因がわからない

わかりやすいように元ネタと同じ構造にしました。

Java

1import java.util.*; 2 3public class Stream { 4 public static void main(String[] args) { 5 var a1 = createMap("Taro", "2018-07-11", "15"); 6 var a2 = createMap("Taro", "2015-11-01", "53"); 7 var a3 = createMap("Taro", "2015-10-31", "54"); 8 9 var a4 = createMap("Hanako", "2017-02-05", "53"); 10 var a5 = createMap("Hanako", "2016-11-01", "160"); 11 var a6 = createMap("Hanako", "2012-08-20", "22"); 12 13 var a7 = createMap("Pochi", "2013-03-16", "38"); 14 var a8 = createMap("Pochi", "2011-09-25", "200"); 15 var a9 = createMap("Pochi", "2018-04-13", "10"); 16 17 var list = Arrays.asList(a1, a2, a3, a4, a5, a6, a7, a8, a9); 18 list.stream().forEach(a -> System.out.println(a.get("contributor") + " " + a.get("date") + " " + a.get("goodCount"))); 19 20 21 System.out.println("\n名前 -> 投稿日でソート"); 22 Comparator<Map<String, String>> comparator = 23 // Stream::は、このクラスのメソッド参照(java.util.stream.Streamとは何の関係もない!) 24 Comparator.comparing(Stream::getContributor).thenComparing(Stream::getDate); 25 26 // ラムダでも書けるがthenComparingがあると、型を明示しないといけないのが少々うっとおしい 27 // [Stream処理における、型推論されない原因がわからない](https://teratail.com/questions/245767) 28 //Comparator.comparing((Map<String, String> a) -> a.get("contributor")).thenComparing(a -> a.get("date")); 29 30 list.stream().sorted(comparator) 31 .forEach(a -> System.out.println(a.get("contributor") + " " + a.get("date") + " " + a.get("goodCount"))); 32 33 34 System.out.println("\n名前 -> いいね数でソート"); 35 comparator = Comparator.comparing(Stream::getContributor).thenComparing(Stream::getGoodCount); 36 list.stream().sorted(comparator) 37 .forEach(a -> System.out.println(a.get("contributor") + " " + a.get("date") + " " + a.get("goodCount"))); 38 } 39 40 private static Map<String, String> createMap(String contributor, String date, String goodCount) { 41 var map = new HashMap<String, String>(); 42 map.put("contributor", contributor); 43 map.put("date", date); 44 map.put("goodCount", goodCount); 45 return map; 46 } 47 48 private static String getContributor(Map<String, String> map) { 49 return map.get("contributor"); 50 } 51 52 private static String getDate(Map<String, String> map) { 53 return map.get("date"); 54 } 55 56 private static String getGoodCount(Map<String, String> map) { 57 return map.get("goodCount"); 58 } 59}
Taro 2018-07-11 15 Taro 2015-11-01 53 Taro 2015-10-31 54 Hanako 2017-02-05 53 Hanako 2016-11-01 160 Hanako 2012-08-20 22 Pochi 2013-03-16 38 Pochi 2011-09-25 200 Pochi 2018-04-13 10 名前 -> 投稿日でソート Hanako 2012-08-20 22 Hanako 2016-11-01 160 Hanako 2017-02-05 53 Pochi 2011-09-25 200 Pochi 2013-03-16 38 Pochi 2018-04-13 10 Taro 2015-10-31 54 Taro 2015-11-01 53 Taro 2018-07-11 15 名前 -> いいね数でソート Hanako 2016-11-01 160 ※ Hanako 2012-08-20 22 Hanako 2017-02-05 53 Pochi 2018-04-13 10 Pochi 2011-09-25 200 ※ Pochi 2013-03-16 38 Taro 2018-07-11 15 Taro 2015-11-01 53 Taro 2015-10-31 54

※ 数値ではなく文字列での比較のため元ネタと順番が違う。

投稿2022/10/05 11:04

TN8001

総合スコア9317

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

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

makoyang

2022/10/06 01:52

親切なご回答、ありがとうございます! 私のレベルを想定して?となりそうなところにコメントが入っていて本当に助かりました。 (案の定というかメソッド参照のところとでは一度?となってしまいました) 頂いた回答のリンク先も参照して、数値での比較や昇順へしてみるなど、すべて想定通りの動きとなりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問