【Java】Map(HashMap・TreeMap)のkey・valueでソートする方法

Mapのキーを指定してソートするためにはどうすればいいの?
Mapの値を指定してソートするためにはどうすればいいの?
昇順と降順でソートするためにはどうすればいいの?
複数キーがある場合はどうやってソートするの?

JavaのMapを扱う上で、データをソート(並べ替え)する処理はよく使います。今回はMapでソートする方法について解説していきます。

この記事では、Mapのソートについて

  • 【基礎】HashMapのソート方法
  • 【基礎】TreeMapのソート方法
  • 【発展】複数のキーでソートする方法

などの基本から発展的な内容についてもわかりやすく解説していきます。

なお、Javaの記事については、こちらにまとめています。

目次

HashMapのソート方法

ここでは、HashMapのソートについて、

  • キー名でソートする方法
  • 値を指定して昇順と降順でソートする方法

の方法をそれぞれ説明します。

キー名でソートする方法

Mapをキー名指定でソートする場合、Objectクラスを使用してMapの要素数を取得し、ソートするためにArrays.sortメソッドを使用します。以下にキー名でソートする方法を記述します。

なお、Arrays.sortメソッドを使用するためには、java.util.Arraysをインポートする必要があります。

import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;

public class Main {
 
    public static void main(String[] args) {
        // Mapの宣言
        Map<Integer, String> mMap = new HashMap<Integer, String>();
        
        // Mapにデータを格納
        mMap.put( 1, "apple");
        mMap.put( 2, "orange");
        mMap.put( 4, "pineapple");
        mMap.put( 5, "strawberry");
        mMap.put( 3, "melon");
        
        // キーでソートする
        Object[] mapkey = mMap.keySet().toArray();
        Arrays.sort(mapkey);
        
        for (Integer nKey : mMap.keySet())
        {
            System.out.println(mMap.get(nKey));
        }
    }
 
}

実行結果:

apple
orange
melon
pineapple
strawberry

このサンプルコードでは、定義したMap変数mMapにキー名が1、2、4、5、3の順に値を設定しています。Objectクラスを宣言し、変数mapkeyにMapの要素を全て取得します。次にArraysクラスのsortメソッドを使用し、Mapのキーをソートしています。

ループでMapの値を確認すると、ソートされていることがわかります。

値でソートする方法(compareToを使用)

ここでは、Mapの値を指定して、昇順と降順それぞれのソートの方法について記載します。

import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Main {
 
    public static void main(String[] args) {
        Map<String, Integer> mMap = new HashMap<String, Integer>();
        
        // 1. Mapにデータを格納
        mMap.put( "apple", 1);
        mMap.put( "orange", 2);
        mMap.put( "pineapple", 4);
        mMap.put( "strawberry", 5);
        mMap.put( "melon", 3);
        
        // 2.Map.Entryのリストを作成する
        List<Entry<String, Integer>> list_entries = new ArrayList<Entry<String, Integer>>(mMap.entrySet());
        
        // 3.比較関数Comparatorを使用してMap.Entryの値を比較する(昇順)
        Collections.sort(list_entries, new Comparator<Entry<String, Integer>>() {
            public int compare(Entry<String, Integer> obj1, Entry<String, Integer> obj2) {
                // 4. 昇順
                return obj1.getValue().compareTo(obj2.getValue());
            }
        });
        
        System.out.println("昇順でのソート");
        // 5. ループで要素順に値を取得する
        for(Entry<String, Integer> entry : list_entries) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
        
        // 6. 比較関数Comparatorを使用してMap.Entryの値を比較する(降順)
        Collections.sort(list_entries, new Comparator<Entry<String, Integer>>() {
            //compareを使用して値を比較する
            public int compare(Entry<String, Integer> obj1, Entry<String, Integer> obj2)
            {
                //降順
                return obj2.getValue().compareTo(obj1.getValue());
            }
        });
        
        System.out.println("降順でのソート");
        // 7. ループで要素順に値を取得する
        for(Entry<String, Integer> entry : list_entries) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }
 
}

実行結果:

昇順でのソート
apple : 1
orange : 2
melon : 3
pineapple : 4
strawberry : 5
降順でのソート
strawberry : 5
pineapple : 4
melon : 3
orange : 2
apple : 1

このサンプルコードのコメントに記載している、1〜7の詳細を以下に説明します。

  1. 定義したMap変数mMapにキー名が1、2、4、5、3の順に値を設定
  2. MapのEntry(キーと値のペア)のリストを作成
  3. Collectionクラスのsortメソッドを使用して、比較関数Comparatorで、MapのEntryの値を比較し、compare関数を使用してMapのEntryのobj1(昇順)、obj2(降順)を定義
  4. compareToメソッドを使用して降順で並べ替えられた要素を返す
  5. ループで要素数を順に表示させていくと、昇順でソートされていく
  6. 降順でソートするときは、compareToメソッドを使用するときに、Entryのobj2(降順)を指定して返せばOK
  7. ループで要素数を順に表示させていくと、降順でソートされていく

TreeMapのソート方法

TreeMapもHashMapと同じようにMapを実装したコレクションクラスです。基本的な使用方法はHashMapと同じですが、TreeMapの特性としてputメソッドで格納した値を内部で自動的にソートして保持されます。以下にTreeMapを使用したサンプルコードを記述します。

なお、TreeMapを使用する際には、java.util.TreeMapをインポートする必要があります。

import java.util.Map;
import java.util.TreeMap;

public class Main {
 
    public static void main(String[] args) {
        // Mapの宣言
        Map<Integer, String> mMap = new TreeMap<Integer, String>();
        
        // Mapにデータを格納
        mMap.put(1, "apple");
        mMap.put(2, "orange");
        mMap.put(5, "pineapple");
        mMap.put(3, "strawberry");
        mMap.put(4, "melon");
        
        // keySetを使用してMapの要素数分ループする
        for (Integer nKey : mMap.keySet())
        {
            System.out.println(mMap.get(nKey));
        }
    }
 
}

実行結果:

apple
orange
strawberry
melon
pineapple

このサンプルコードでは、キーを1、2、5、3、4の順に格納していますが、実行結果の値を確認すると、値のキーがソートされていることがわかります。

複数のキーでソートする方法

ここでは、MapとListが入れ子になっている場合にソートする方法を紹介します。

import java.util.Map;
import java.util.Map.Entry;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Main {
 
    public static void main(String[] args) {
        // Map(mMap1)の宣言
        Map<List, Integer> mMap1 = new HashMap<List, Integer>();
        // list(lList1)の宣言
        List<String> lList1 = new ArrayList<String>();
        
        lList1.add("apple");
        
        mMap1.put(lList1, 2);
        
        // list(lList2)の宣言
        List<String> lList2 = new ArrayList<String>();
        
        lList2.add("orange");
        
        mMap1.put(lList2, 3);
        
        // list(lList3)の宣言
        List<String> lList3 = new ArrayList<String>();
        
        lList3.add("melon");
        
        mMap1.put(lList3, 1);
        
         // Map.Entry のリストを作る
        List<Entry<List, Integer>> list_entries = new ArrayList<Entry<List, Integer>>(mMap1.entrySet());
        
        // 比較関数Comparatorを使用してMap.Entryの値を比較する
        Collections.sort(list_entries, new Comparator<Entry<List, Integer>>() {
            // compareを使用して値を比較する
            public int compare(Entry<List, Integer> obj1, Entry<List, Integer> obj2) {
                return obj1.getValue().compareTo(obj2.getValue());
            }
        });
        
        // ループでリストの中身を表示する
        for(Entry<List, Integer> entry : list_entries) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }
 
}

実行結果:

[melon] : 1
[apple] : 2
[orange] : 3

このサンプルコードでは、Map変数mMap1に、作成したlList1、lList2、lList3をそれぞれMapの値2、3、1の順に格納しています。次にMapの値でのソート方法同様に、MapのEntryのリストを作成して、比較関数を使用してソートした結果を返しています。

Mapについてもっと詳しく知りたい方へ

Mapのさまざまな使い方については以下の記事にまとめていますので、ぜひ参考にしてくださいね!

compareToで大小を比較する方法総まとめ

compareToメソッドで大小を比較するいろいろな方法を次の記事にまとめているので、ぜひ確認してください!

まとめ

ここでは、Mapでのキー名を指定してのソート、値を指定してのソート、昇順・降順でのソートなどを一通り説明しました。MapやListなどのコレクションをソートする方法は、何パターンかありますが、慣れないうちは難しく感じるかもしれません。

もし、Mapでのソートをする方法を忘れてしまったら、この記事を思い出してくださいね!

この記事を書いた人

【プロフィール】
DX認定取得事業者に選定されている株式会社SAMURAIのマーケティング・コミュニケーション部が運営。「質の高いIT教育を、すべての人に」をミッションに、IT・プログラミングを学び始めた初学者の方に向け記事を執筆。
累計指導者数4万5,000名以上のプログラミングスクール「侍エンジニア」、累計登録者数1万8,000人以上のオンライン学習サービス「侍テラコヤ」で扱う教材開発のノウハウ、2013年の創業から運営で得た知見に基づき、記事の執筆だけでなく編集・監修も担当しています。
【専門分野】
IT/Web開発/AI・ロボット開発/インフラ開発/ゲーム開発/AI/Webデザイン

目次