Java - HashMapソート、4つの方法

JavaでHashMapまたはMapをソートするさまざまな方法を紹介します。

HashMapは、入力するデータの順序を保証しないデータ構造です。そのため、他のデータ構造を使用してHashMapの要素を整列させる必要があります。

1. Listを使ってHashMapを並べ替える

keySet() または values() は、 HashMap に格納されているすべての key と value を List として返します。

リストは順序付きのデータ構造であるため、keyまたはvalueのリストを任意の方法でソートできます。 keyまたはvalueの中で1種類だけソートが必要な場合は、この方法を使用してください。

1.1 Keyでソート(Sort by key)

次のコードは、キーを含むリストを昇順にソートします。

import java.util.*;

public class Example {

    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>();
        map.put("Nepal", "Kathmandu");
        map.put("United States", "Washington");
        map.put("India", "New Delhi");
        map.put("England", "London");
        map.put("Australia", "Canberra");

        List<String> keyList = new ArrayList<>(map.keySet());
        keyList.sort((s1, s2) -> s1.compareTo(s2));
        for (String key : keyList) {
            System.out.println("key: " + key + ", value: " + map.get(key));
        }
    }
}

結果

key: Australia, value: Canberra
key: England, value: London
key: India, value: New Delhi
key: Nepal, value: Kathmandu
key: United States, value: Washington

ちなみに、上記のコードでComparator (s1, s2)->s1.compareTo(s2)は以下のコードのようにメソッドリファレンスを使用してString::compareToで置き換えることができます。

keyList.sort(String::compareTo);

1.2 Value でソートする(Sort by value)

次のコードは、value を含む List を昇順にソートします。

import java.util.*;

public class Example {

    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>();
        map.put("Nepal", "Kathmandu");
        map.put("United States", "Washington");
        map.put("India", "New Delhi");
        map.put("England", "London");
        map.put("Australia", "Canberra");

        List<String> valueList = new ArrayList<>(map.values());
        valueList.sort(String::compareTo);
        for (String value : valueList) {
            System.out.println("Value: " + value);
        }
    }
}

結果

Value: Canberra
Value: Kathmandu
Value: London
Value: New Delhi
Value: Washington

2. TreeMapを使用したHashMapの並べ替え

TreeMapはオブジェクトを作成するときに引数としてComparatorを渡すことができ、要素を追加するときにComparatorを使ってキーをソートし、その順序で保存されます。つまり、データをインポートするときは、すでにソートされた順序で返され、再ソートする必要はありません。

以下の例では、Comparatorはキーを昇順にソートするように実装し、これをTreeMapコンストラクタの引数として渡してオブジェクトを作成しました。

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

public class Example {

    public static void main(String[] args) {

        Comparator<String> comparator = (s1, s2) -> s1.compareTo(s2);
        Map<String, String> map = new TreeMap<>(comparator);
        map.put("Nepal", "Kathmandu");
        map.put("United States", "Washington");
        map.put("India", "New Delhi");
        map.put("England", "London");
        map.put("Australia", "Canberra");

        for (Map.Entry<String, String> entry : map.entrySet()) {
            System.out.println("Key: " + entry.getKey() + ", "
                    + "Value: " + entry.getValue());
        }
    }
}

出力してみると、キーが昇順にソートされて出力されます。

Key: Australia, Value: Canberra
Key: England, Value: London
Key: India, Value: New Delhi
Key: Nepal, Value: Kathmandu
Key: United States, Value: Washington

TreeMapはvalueをソートしないため、キーをソートする場合にのみ使用できます。

Comparator、Comparableクラス内で要素をどのようにソートするかについての内容が実装されています。詳細については、Comparatorでソートする方法またはComparableでソート(Sorting)する方法を参照してください。

3. Streamを使用したHashMapの並べ替え

Streamを使用してHashMapを並べ替えることもできます。

次のコードは、Streamを使用して値またはキーに基づいてソートするコードです。 Stream で sorted(Map.Entry.comparingByKey()) 同じコードで key や value をソートできます。

import java.util.*;
import java.util.stream.Collectors;

public class Example {

    public static void main(String[] args) {

        Map<String, String> map = new HashMap<>();
        map.put("Nepal", "Kathmandu");
        map.put("United States", "Washington");
        map.put("India", "New Delhi");
        map.put("England", "London");
        map.put("Australia", "Canberra");

        // sort by key
        List<Map.Entry<String, String>> entries =
                map.entrySet().stream()
                        .sorted(Map.Entry.comparingByKey())
                        .collect(Collectors.toList());
        for (Map.Entry<String, String> entry : entries) {
            System.out.println("Key: " + entry.getKey() + ", "
                    + "Value: " + entry.getValue());
        }

        // sort by value
        System.out.println();
        entries = map.entrySet().stream()
                .sorted(Map.Entry.comparingByValue())
                .collect(Collectors.toList());
        for (Map.Entry<String, String> entry : entries) {
            System.out.println("Key: " + entry.getKey() + ", "
                    + "Value: " + entry.getValue());
        }
    }
}

結果

Key: Australia, Value: Canberra
Key: England, Value: London
Key: India, Value: New Delhi
Key: Nepal, Value: Kathmandu
Key: United States, Value: Washington

Key: Australia, Value: Canberra
Key: Nepal, Value: Kathmandu
Key: England, Value: London
Key: India, Value: New Delhi
Key: United States, Value: Washington

Streamでsorted()でソートされたアイテムを直接出力してもよいが、collect()でListを返すようにしました。

4. LinkedHashMapを使用したHashMapの並べ替え

LinkedHashMapは、Mapに入力した順序が保証されるクラスです。つまり、LinkedHashMapに入力する順番でソートされ、この順番でデータを再取り出すことができます。 Mapを使用していますが、入力した順序でMapに保存したい場合は、LinkedHashMapを使用できます。

面倒な方法ですが、HashMapのキーリストを並べ替え、並べ替えられた順番でLinkedHashMapに入力すると、入力された順番で保存されます。 LinkedHashMapから順に要素を読み取ると、ソートされた順序で読み取ることができます。

4.1 Keyでソート(Sort by key)

Map.Entryをリストに取り、キー値でソートし、ソートされた順序でLinkedHashMapに追加します。

実装されたコードは次のとおりです。

import java.util.*;

public class Example {

    public static LinkedHashMap<String, String> sortMapByKey(Map<String, String> map) {
        List<Map.Entry<String, String>> entries = new LinkedList<>(map.entrySet());
        Collections.sort(entries, (o1, o2) -> o1.getKey().compareTo(o2.getKey()));

        LinkedHashMap<String, String> result = new LinkedHashMap<>();
        for (Map.Entry<String, String> entry : entries) {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

    public static void main(String[] args) {

        Map<String, String> map = new LinkedHashMap<>();
        map.put("Nepal", "Kathmandu");
        map.put("United States", "Washington");
        map.put("India", "New Delhi");
        map.put("England", "London");
        map.put("Australia", "Canberra");

        Map<String, String> result = sortMapByKey(map);
        for (Map.Entry<String, String> entry : result.entrySet()) {
            System.out.println("Key: " + entry.getKey() + ", "
                    + "Value: " + entry.getValue());
        }
    }
}

結果を見ると、キーを基準に昇順にソートされました。 (アルファベット順)

Key: Australia, Value: Canberra
Key: England, Value: London
Key: India, Value: New Delhi
Key: Nepal, Value: Kathmandu
Key: United States, Value: Washington

4.2 Value でソートする(Sort by value)

Map.Entryをリストに取り、valueに基づいてソートし、ソートされた順序でLinkedHashMapに追加します。

実装されたコードは次のとおりです。

import java.util.*;

public class Example {

    public static LinkedHashMap<String, String> sortMapByValue(Map<String, String> map) {
        List<Map.Entry<String, String>> entries = new LinkedList<>(map.entrySet());
        Collections.sort(entries, (o1, o2) -> o1.getValue().compareTo(o2.getValue()));

        LinkedHashMap<String, String> result = new LinkedHashMap<>();
        for (Map.Entry<String, String> entry : entries) {
            result.put(entry.getKey(), entry.getValue());
        }
        return result;
    }

    public static void main(String[] args) {

        Map<String, String> map = new LinkedHashMap<>();
        map.put("Nepal", "Kathmandu");
        map.put("United States", "Washington");
        map.put("India", "New Delhi");
        map.put("England", "London");
        map.put("Australia", "Canberra");

        Map<String, String> result = sortMapByValue(map);
        for (Map.Entry<String, String> entry : result.entrySet()) {
            System.out.println("Key: " + entry.getKey() + ", "
                    + "Value: " + entry.getValue());
        }
    }
}

結果を見ると、valueを基準に昇順にソートされました。 (アルファベット順)

Key: Australia, Value: Canberra
Key: Nepal, Value: Kathmandu
Key: England, Value: London
Key: India, Value: New Delhi
Key: United States, Value: Washington

References

codechachaCopyright ©2019 codechacha