
下記のような<String, List>の型を持つmapの中身をList型のバリューで昇順にソートをしたいですが,実装方法が分かりません。
※バリューのList[0]の値で昇順にしたいです。
HashMap<String, List> map = new HashMap<String, List>();
map.put(key, listOTbject);※loopで下記に示すような4つのデータをmapに詰め込む処理あり
--現在のmapのデータ格納イメージ
<1,[30,aaa]>
<2,[60,abc]>
<3,[40,abc]>
<4,[70,abc]>
--理想のmapのデータ格納イメージ
<1,[30,aaa]>
<3,[40,abc]>
<2,[60,abc]>
<4,[70,abc]>
※バリューのList[0]でソートされている状態
格納時にソートする方法,もしくは格納後に並び替えを行う方法があればご教示いただければ幸いです。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答4件
0
ベストアンサー
まず、Map自体には順序を持つ機能はありません(SortedMapなどもありますが、キーによる順序付けなので割愛します)。
値によるソートを行いたい場合、順序を保持するためのリスト等を別途用意する必要があります。
キーと値の一覧はMap.entrySetメソッドを呼び出すことで取得できます。
ソート処理は独自のルールを設定する必要があるため、java.util.Comparatorインターフェースの実装が必要です(下記ソースのValueListComparatorを参考にしてください)。
Comparatorを実装したら、Collections.sortを使用することで、ソートを行えます。
java
1import java.util.*; 2public class Test{ 3 public static void main(String[] args){ 4 HashMap<String, List> map = new HashMap<>(); 5 map.put("1",Arrays.asList(30,"aaa")); 6 map.put("2",Arrays.asList(60,"abc")); 7 map.put("3",Arrays.asList(40,"abc")); 8 map.put("4",Arrays.asList(70,"abc")); 9 10 // 順序を保持するためのリスト(Map.entrySetでキーと値の一覧が取得できます) 11 List<Map.Entry<String,List>> mapOrderList = new ArrayList<>(map.entrySet()); 12 13 // ソートの方法を指定してソート実施 14 Collections.sort(mapOrderList, new ValueListComparator()); 15 16 // ソートの結果を出力 17 for(int i=0; i<mapOrderList.size(); ++i){ 18 Map.Entry<String, List> entry= mapOrderList.get(i); 19 System.out.println( 20 i + "番目:" + 21 "<" + entry.getKey() + ", " + entry.getValue() + ">"); 22 } 23 } 24 25 // ソートの方法を決める処理 26 private static class ValueListComparator 27 implements Comparator<Map.Entry<String, List>>{ 28 29 public int compare(Map.Entry<String, List> object1, 30 Map.Entry<String, List> object2){ 31 32 // マップの値 33 List object1List = object1.getValue(); 34 List object2List = object2.getValue(); 35 36 // リストの1番目 37 Comparable object1ListFirst = (Comparable)object1List.get(0); 38 Comparable object2ListFirst = (Comparable)object2List.get(0); 39 40 return object1ListFirst.compareTo(object2ListFirst); 41 } 42 } 43}
実行結果
0番目:<1, [30, aaa]> 1番目:<3, [40, abc]> 2番目:<2, [60, abc]> 3番目:<4, [70, abc]>
投稿2018/03/13 11:35
総合スコア149
0
Mapには「順序はない」と考えるのが普通です。ただし例外的にjava.util.LinkedHashMapというクラスがありキーを挿入した順番でエントリー(キーや値)の列挙が可能です。これは主としてLRUキャッシュ目的で使うものという印象で、自分はLRUキャッシュ以外で使ったことがありませんが、構築後に一切内容を変更しないなら、これを使えばご質問のようなMapが作れます。(一旦作った後にソートしなおすなら作り直しになります。あくまでキーの登録順に並びますので)
ただしLinkedHashMapもあくまでMapであってListではありませんので「i番目の値」なんてアクセス(ランダムアクセス)はできません。
自分にはなんでMapをソートしなきゃいけないのかがよくわかりません。Mapってのは「任意のキーによって値を取り出す連想配列」です。値の順番に内部を並び替えると何かの処理にとって都合がよくなるのかも知れませんが・・・一つのもの(Map => 連想配列)にそれとは違う別の機能(順番付きの列)を期待するのはあまり筋が良いことではない気がします。
ある順番に取り出したいのなら、別途Map.Entryを順序付きの列(List)に取り出し、それを望む順にソートすればいいのではないかという気がします。MapはMap目的で使い、順序の意識は順序付きのコレクション(List)に任せた方がわかりやすいんじゃないでしょうか。
投稿2018/03/13 11:36
編集2018/03/14 03:22総合スコア18404
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。


0
みなさんの回答にもありますが、基本的にMapに順序という考え方はありません。
Mapへの突っ込み順を保持するLinkedHashMapで作り直せば可能ではありますが、
作ったLinkedHashMapに新たにputしてしまうと、並び替えた順序は破綻します。
Java
1Map<String, List<?>> newMap = map.entrySet().stream() 2 .sorted(Comparator.comparing(entry -> (Integer) ((Entry<String, List<?>>) entry).getValue().get(0))) 3 .collect(Collectors.toMap(Entry::getKey, Entry::getValue, (l1, l2) -> l2, LinkedHashMap::new));
投稿2018/03/14 01:51
編集2018/03/14 01:55総合スコア4666
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
https://docs.oracle.com/javase/jp/8/docs/api/java/util/Comparator.html
このインタフェースを継承して好きなように実装してください
投稿2018/03/13 10:27

退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/03/14 08:17
2018/03/14 08:24
2018/03/14 08:33 編集
2018/03/14 08:33
2018/03/14 08:37