Java で HashMap をキーで並べ替える

Rashmi Patidar 2023年10月12日
  1. Java の TreeMap クラスを使用してキーセットを並べ替える
  2. Java 8 関数を使用したキーセットのソート
  3. Java のマップ初期化ストリーム関数を理解する
  4. Java のマップ変換ストリーム関数を理解する
Java で HashMap をキーで並べ替える

Java 言語の HashMap という用語は、Map インターフェースから派生したコレクションです。このコレクションまたはクラスは java.util パッケージに含まれており、データをキーと値のペアで格納します。マップ上に 2つのキーを含めることはできないことに注意してください。重複するキーが挿入されると、それぞれのキーの値が新しい値に置き換えられます。

Java の TreeMap クラスを使用してキーセットを並べ替える

以下は、HashMap をキーでソートする方法を示すコードブロックです。

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

public class HashMapSortByKey {
  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    map.put("2", "Value5");
    map.put("3", "Value1");
    map.put("1", "Value2");
    map.put("4", "Value3");
    map.put("9", "Value4");
    map.put("hi11", "Value6");
    map.put("hi0", "Value7");
    System.out.print("Unordered List: ");
    for (String s : map.keySet()) {
      System.out.print(" " + s);
    }
    System.out.println();
    System.out.print("Ordered List: ");
    TreeMap<String, String> map1 = new TreeMap<>(map);
    for (String s : map1.keySet()) {
      System.out.print(" " + s);
    }
  }
}

上記のコードブロックでは、map オブジェクトは、new キーワードを指定した HashMap のデフォルトコンストラクターを使用して宣言されています。このステートメントは、HashSet クラスのインスタンスを作成し、その値を Map インターフェイス参照に割り当てます。HashMap クラスは Map インターフェースを内部的に実装するため、タイプは互換性があります。

マップは、いくつかのキー値のセットで初期化されます。挿入は、キーを指定された値にバインドする put メソッドを使用して行われます。キーがマップにすでに存在する場合、メソッドは previous value を返し、前の値を指定された値でオーバーライドします。キーがマップにまだ存在しない場合、関数は null 値を返します。キーまたは値のプロパティで値の挿入が禁止されている場合は、IllegalArgumentException がスローされます。

マップを反復処理するために、for-each ループが使用されます。map.keySet 関数は、マップ内のすべてのキーの Set 形式を返します。キーセット関数は、変数が反復できる for-each ループでコレクションを取得します。したがって、キーを出力します。値は順序付けられていない形式で出力され、ユーザーが出力を取得する明確な方法はありません。

マップキーをソートするために、TreeSet クラスが使用されます。map 変数は、インスタンス化時に TreeSet コンストラクターのコンストラクターパラメーターとして指定されます。このクラスは、キーをソートするための Comparable インターフェースを実装しています。結果のマップ map1 が出力されると、ソートされたキーが出力に出力されます。

以下は、上記のコードブロックの出力です。

出力:

Unordered List:  1 hi11 2 3 4 9 hi0
Ordered List:  1 2 3 4 9 hi0 hi11

Java 8 関数を使用したキーセットのソート

Java 8 は、関数型プログラミングの特権を提供します。これは、チェーン関数の操作に役立ちます。以下のプログラムでは、インスタンス化と初期化がステートメントで行われていることがわかります。一方、最初のサンプルコードでは、マップにデータを入力するのは面倒な作業です。単一のステートメントでマップをインスタンス化するための Stream と関数の理解を以下に示します。

Streamsjava.util パッケージのインターフェースであり、操作のシーケンスを一度に処理する柔軟性を提供します。Streams は、エミッターがデータを送信するパイプラインで機能します。ユーザーのニーズに応じて、フィルタリング、処理、変換などが行われます。

import static java.util.AbstractMap.SimpleEntry;
import static java.util.stream.Collectors.toMap;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Stream;

public class HashMapSortByKey {
  public static void main(String[] args) {
    Map<String, String> map =
        Stream
            .of(new SimpleEntry<>("key6", "value1"), new SimpleEntry<>("key12", "value2"),
                new SimpleEntry<>("key9", "value3"))
            .collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue));

    System.out.print("Unordered List: ");
    for (String s : map.keySet()) {
      System.out.print(" " + s);
    }
    Map<String, String> mapSortedByKey =
        map.entrySet()
            .stream()
            .sorted(Map.Entry.<String, String>comparingByKey().reversed())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                (oldVal, newValue) -> oldValue, LinkedHashMap::new));

    System.out.println();
    System.out.print("Ordered List: ");
    for (String s1 : mapSortedByKey.keySet()) {
      System.out.print(" " + s1);
    }
  }
}

Java のマップ初期化ストリーム関数を理解する

まず、Stream は、指定されたストリームを順番に返す of() 関数を呼び出します。この関数は、SimpleEntry クラスのオブジェクトを作成して、Key-Value フォームのマッピングを作成します。このクラスは Entry インターフェースを実装し、マップのコレクションビューを返す entrySet メソッドを持っています。

Key-Value エントリが形成されると、collect 関数を使用して値がマップに収集されます。これはターミナル関数であり、collect 関数の後にメソッドを呼び出すことはできません。この関数は、ストリーム値を目的のデータ構造にパッケージ化またはバインドします。

パラメータとして指定された入力は、常に Collector 参照です。toMap は、マップ内のストリーム要素をバインドする Collector を返す Collectors クラスの静的関数です。この関数は、キーマッパーとキー値関数をパラメーターとして受け取ります。ここで、メソッド参照::演算子は、指定されたクラスの関数を呼び出すことを意味します。

キーマッパーでは、getKey 関数が入力された EntrySet ストリームからキーを抽出します。同様に、Key Value 関数では、getValue 関数が呼び出されて、EntrySet ストリームから値を取得します。

上記のコードの Collector``Function 変数は、機能のための単一の抽象メソッドを持つ Java の機能インターフェイスです。抽象メソッドの定義は、それらを実装するクラスで定義されます。

Java のマップ変換ストリーム関数を理解する

形成されたばかりの map インスタンス上で、entrySet 関数が呼び出されます。この関数は、マップエントリのセットビューを返し、マップインターフェイスに存在します。これらのエントリに対して、stream メソッドが呼び出され、シーケンシャルストリームのエントリが変換されます。エントリのストリームを介して、sorted 関数が呼び出されます。

Stream 要素を比較するには、コンパレータが必要です。ソートされた関数は、最終的に、指定されたエントリのソートされたストリームを返します。comparingByKey 関数は、キーのデフォルトの順序で Map.Entry コンパレータを返します。コンパレータはキーセットを返します。見つかったキーが null の場合、関数から NullPointerException がスローされます。

エントリセットが取得されると、コレクション内の要素の順序を逆にするために reversed 関数が呼び出されます。最後に、collect 関数がマップストリームを介して呼び出されます。この関数は端末演算子であるため、collect 関数の後に操作を呼び出すことはできません。関数内で、toMap 関数が呼び出され、ストリームがマップに変換されます。

この関数は 4つのパラメーターを取ります。keyMapper はキーを生成する関数、valueMapper はその値を作成するマッピング関数、mergeFunction は関数をマージする BinaryOperatormapSupplier は結果が挿入される新しい空のマップを返す Supplier 関数。最後に、結果のコンソール出力が上に出力されます。

出力:

Unordered List:  key12 key6 key9
Ordered List:  key9 key6 key12
著者: Rashmi Patidar
Rashmi Patidar avatar Rashmi Patidar avatar

Rashmi is a professional Software Developer with hands on over varied tech stack. She has been working on Java, Springboot, Microservices, Typescript, MySQL, Graphql and more. She loves to spread knowledge via her writings. She is keen taking up new things and adopt in her career.

LinkedIn

関連記事 - Java HashMap