1前書き

このクイックチュートリアルでは、** Javaで

HashMap

をソートする方法を学びます。

具体的には、次のようにして

HashMap

エントリをキーまたは値でソートする方法を見ていきます。


  • TreeMap


  • ArrayList

    および

    Collections.sort()


  • TreeSet


  • Stream

    APIの使用

    __、

    __そして最後に、


  • __Guava

    __libraryの使用


2

TreeMap


を使う

私たちが知っているように、

TreeMap



キーはそれらの自然な順序

を使ってソートされています。

キーと値のペアをキーでソートしたい場合、これは良い解決策です。つまり、すべてのデータを

HashMap

からhttps://www.baeldung.com/java-treemap[

TreeMap

]にプッシュすることです。

まず始めに、

HashMap

を定義し、それをデータで初期化しましょう:

Map<String, Employee> map = new HashMap<>();

Employee employee1 = new Employee(1L, "Mher");
map.put(employee1.getName(), employee1);
Employee employee2 = new Employee(22L, "Annie");
map.put(employee2.getName(), employee2);
Employee employee3 = new Employee(8L, "John");
map.put(employee3.getName(), employee3);
Employee employee4 = new Employee(2L, "George");
map.put(employee4.getName(), employee4);


Employee

クラスの場合、

Comparable

:** が実装されていることに注意してください。

public class Employee implements Comparable<Employee> {

    private Long id;
    private String name;

   //constructor, getters, setters

   //override equals and hashCode
    @Override
    public int compareTo(Employee employee) {
        return (int)(this.id - employee.getId());
    }
}

次に、コンストラクタを使ってエントリを

__TreeMap

__byに格納します。

TreeMap<String, Employee> sorted = new TreeMap<>(map);

または、

putAll

メソッドでデータをコピーします。

TreeMap<String, Employee> sorted = new TreeMap<>();
sorted.putAll(map);

以上です!マップのエントリがキーでソートされていることを確認するために、それらを印刷してみましょう。

Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Mher=Employee{id=1, name='Mher'}

ご覧のとおり、キーは自然な順序で並べ替えられています。


3

ArrayList


を使用する

もちろん、

ArrayList

を使用してマップのエントリを並べ替えることができます。前の方法との主な違いは、

Map

インターフェースをここでは保守しないことです。


3.1. キー順で並べ替え

キーセットを

ArrayList

にロードしましょう。

List<String> employeeByKey = new ArrayList<>(map.keySet());
Collections.sort(employeeByKey);

そして出力は次のとおりです。

----[Annie, George, John, Mher]----


3.2. 値で並べ替え

それでは、マップ値を

Employee

オブジェクトの

id

フィールドで並べ替える場合はどうなりますか。そのためにも

ArrayList

を使用できます。

まず、値をリストにコピーしましょう。

List<Employee> employeeById = new ArrayList<>(map.values());

その後、並べ替えます。

Collections.sort(employeeById);


  • Employee



    Comparable

    インターフェース** を実装しているので、これはうまくいくことを忘れないでください。それ以外の場合は、

    Collections.sort

    を呼び出すための手動コンパレータを定義する必要があります。

結果を確認するために、

employeeById

を印刷します。

----[Employee{id=1, name='Mher'},
Employee{id=2, name='George'},
Employee{id=8, name='John'},
Employee{id=22, name='Annie'}]----

ご覧のとおり、オブジェクトは

id

フィールドでソートされています。


4

TreeSet


を使う

ソートされたコレクションで重複した値を受け入れたくない場合は、__TreeSetを使った良い解決策があります。

まず、最初のマップに重複したエントリを追加しましょう。

Employee employee5 = new Employee(1L, "Mher");
map.put(employee5.getName(), employee5);
Employee employee6 = new Employee(22L, "Annie");
map.put(employee6.getName(), employee6);


4.1. キー順で並べ替え

キーエントリでマップをソートするには

SortedSet<String> keySet = new TreeSet<>(map.keySet());


keySet

を印刷して出力を確認しましょう。

----[Annie, George, John, Mher]----

これで、マップキーが重複せずにソートされました。


4.2. 値で並べ替え

同様に、マップ値の場合、変換コードは次のようになります。

SortedSet<Employee> values = new TreeSet<>(map.values());

そして結果は次のとおりです。

----[Employee{id=1, name='Mher'},
Employee{id=2, name='George'},
Employee{id=8, name='John'},
Employee{id=22, name='Annie'}]----

ご覧のとおり、出力に重複はありません。 ** これは

equals

と__hashCodeをオーバーライドするときにカスタムオブジェクトで動作します。


5ラムダとストリームの使用

  • Java 8以降、ストリームAPIとラムダ式を使用してマップをソートできます** 。必要なのは、マップの

    stream


    パイプラインで

    sorted__メソッドを呼び出すだけです。


5.1. キー順で並べ替え

キーでソートするには、

__ comparingByKey

__comparatorを使います。

map.entrySet()
  .stream()
  .sorted(Map.Entry.<String, Employee>comparingByKey())
  .forEach(System.out::println);

最後の

forEach

ステージは結果を出力します。

Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Mher=Employee{id=1, name='Mher'}

デフォルトでは、ソートモードは昇順です。


5.2. 値で並べ替え

もちろん、

Employee

オブジェクトによってもソートできます。

map.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByValue())
  .forEach(System.out::println);

ご覧のとおり、上記のコードは

Employee

オブジェクトの

id

フィールドでソートされたマップを出力します。

Mher=Employee{id=1, name='Mher'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}

さらに、結果を新しいマップにまとめることができます。

Map<String, Employee> result = map.entrySet()
  .stream()
  .sorted(Map.Entry.comparingByValue())
  .collect(Collectors.toMap(
    Map.Entry::getKey,
    Map.Entry::getValue,
    (oldValue, newValue) -> oldValue, LinkedHashMap::new));

  • デフォルトでは、

    Collectors.toMap

    は新しいHashMapを返しますが、**

    HashMap

    は繰り返しを保証するものではありません。


6. Guava

を使う

最後に、

HashMap

のソートを可能にするライブラリはGuavaです。始める前に、https://www.baeldung.com/guava-maps[maps in Guava]についての記事を確認すると便利です。

まず、地図を

従業員の

Id

フィールドで並べ替えたいので、https://www.baeldung.com/guava-ordering[

Ordering__]を宣言しましょう。

Ordering naturalOrdering = Ordering.natural()
  .onResultOf(Functions.forMap(map, null));

さて、必要なのは

__ImmutableSortedMap

__を使って結果を説明することだけです。

ImmutableSortedMap.copyOf(map, naturalOrdering);

繰り返しますが、出力は

id

フィールドで並べられたマップです。

Mher=Employee{id=1, name='Mher'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}


7. 概要

この記事では、

__HashMapを

__byキーまたは値でソートする方法をいくつか紹介しました。

そして、

Comparable

を実装することで、属性がカスタムクラスの場合にこれを実行する方法を詳しく調べました。

最後に、いつものように、ディスカッション中に使用されたコードはhttps://github.com/eugenp/tutorials/tree/master/java-collections-maps[GitHubについて]にあります。