JavaRush /Java Blog /Random-JA /Java の HashMap - それはどのようなマップですか?

Java の HashMap - それはどのようなマップですか?

Random-JA グループに公開済み
こんにちは!今日は別のデータ構造であるマップについて説明します。ロシア語の正式名称は「連想配列」ですが、あまり使用されません。より一般的なオプションは、「dictionary」、「map」、または (ほとんどの場合) 英語圏のスラングである「map」です :) Map 内では、データは「キー」と「値」の形式、つまりペアで保存されます。キーと値は両方とも、数値、文字列、または他のクラスのオブジェクトなど、任意のオブジェクトにすることができます。

Map が他のデータ構造と異なる点

前回は、要素が単独で格納されるデータ構造について説明しました。配列、またはArrayList / LinkedListには、特定の数の要素が格納されます。しかし、私たちのタスクが少し変わったらどうなるでしょうか? たとえば、100 人のリストを作成し、その人のフルネームとパスポート番号を保存するというタスクに直面していると想像してください。原理的には、それほど難しいことではありません。たとえば、両方を 1 行に収めて、 「Anna Ivanovna Reshetnikova, 4211 717171」のような行のリストを作成できます。 しかし、この解決策には 2 つの欠点があります。まず、パスポートの検索機能が必要になるかもしれません。そして、情報を保存するためのこの形式では、これは問題になります。そして第二に、同じパスポート番号を持つ 2 人の異なる人物を作成することを妨げるものは何もありません。そして、これが私たちのソリューションの最も深刻な欠点です。このような状況は完全に排除されるべきであり、同じパスポート番号を持つ人は 2 人も存在しません。ここで、Map とその記述された機能が役に立ちます (データを「キー」-「値」形式でペアで保存します)。最も一般的な Map 実装であるJava HashMap クラスを見てみましょう。HashMap - これはどのような地図ですか?  - 1

Java で HashMap を作成し、クラスを操作する

この実装は非常に簡単に作成できます。
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

}
ここでは、要素が「数値文字列」形式で保存される辞書を作成しました。数値がキーとなり、文字列が値となります。Integerまた、どのようなタイプのキー ( ) とどのようなタイプの値 ( )があるかも示しましたString。なぜそうなるのでしょうか? まず、HashMap 内のキーは常に一意です。パスポート番号をキーとして使用し、重複を避けることができるため、これは非常にうまく機能します。フルネームを含む行は値として機能します (さまざまな人々のフルネームを簡単に繰り返すことができますが、それは私たちにとって問題ありません)。

HashMap への新しいペアの追加

このタスクは次のようになります。
public class Main {

   public static void main(String[] args) {
       HashMap<Integer, String> passportsAndNames = new HashMap<>();


       passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
       passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
       passportsAndNames.put(8082771, "Donald John Trump");
       System.out.println(passportsAndNames);

   }

}
これには メソッドが使用されますput()。さらに、HashMap にはオーバーライドされたメソッドがあるtoString()ため、コンソールに出力できます。出力は次のようになります: {212133=Lidiya Arkadyevna Bublikova、8082771=Donald John Trump、162348=Ivan Mikhailovich Serebryakov}

HashMap キーの特徴

では、キーが本当に一意であるかどうかを確認してみましょう。マップ内に すでに存在するキーを持つ新しい要素を追加してみましょう。
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");
   passportsAndNames.put(162348, "Viktor Mikhailovich Stychkin");//repeat key

   System.out.println(passportsAndNames);

}
出力: {212133=Lidiya Arkadyevna Bublikova、8082771=Donald John Trump、162348=Viktor Mikhailovich Stychkin} ご覧のとおり、キー 162348 を持つ前の要素は上書きされました。「The Key」が鍵と呼ばれたのには理由があります。HashMap 内の値はキーによってアクセスされます(ただし、その逆はありません。値は重複する可能性があるため、値によってキーを取得することはできません)。これは、要素を取得する例と、HashMap から要素を削除する例ではっきりとわかります。
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   String lidiaName = passportsAndNames.get(212133);
   System.out.println(lidiaName);


   passportsAndNames.remove(162348);
   System.out.println(passportsAndNames);

}
値を取得するか、辞書からペアを削除するには、この値に対応する一意のキーをget()メソッドに正確に渡す必要があります。HashMap には、配列やリストのような数値インデックスはありません。値はキーによってアクセスされます。コンソール出力: リディヤ・アルカディエフナ・ブブリコワ {212133=リディヤ・アルカディエフナ・ブブリコワ、8082771=ドナルド・ジョン・トランプ}remove()

キーと値の存在を確認する

ArrayList クラスLinkedListクラスでは、リストに特定の要素が含まれているかどうかを確認できます。 HashMapcontainsKey()を使用すると、ペアの両方の部分でこれを行うこともできます。HashMap には、メソッド(キーの存在をチェックする) とcontainsValue()(値の存在をチェックする) があります。
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");


   System.out.println(passportsAndNames.containsKey(11111));
   System.out.println(passportsAndNames.containsValue("Donald John Trump"));

}
出力: false true

すべてのキーと値のリストの取得

HashMap のもう1 つの便利な機能は、すべてのキーとすべての値のリストを個別に取得できることです。このために、メソッドkeySet()とメソッドが使用されますvalues()
public class Main {

   public static void main(String[] args) {

       HashMap<Integer, String> passportsAndNames = new HashMap<>();

       passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
       passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
       passportsAndNames.put(8082771, "Donald John Trump");

       Set<Integer> keys = passportsAndNames.keySet();
       System.out.println("Keys: " + keys);

       ArrayList<String> values = new ArrayList<>(passportsAndNames.values());
       System.out.println("Values: " + values);

   }

}
キーはコレクションに抽出されますSet。その特徴は、繰り返し要素を含めることができないことです。ここで覚えておくべき主な点は、すべてのキーのリストを HashMap から取り出して別のコレクションにできるということです。この例では、値を Normal に保存しましたArrayList。コンソール出力: キー: [212133, 8082771, 162348] 値: [Lidiya Arkadyevna Bublikova、Donald John Trump、Ivan Mikhailovich Serebryakov] メソッドは、これまでに説明した構造とまったく同じことsize()を行いますclear()。最初のメソッドは数値要素を返します。現時点の辞書では、2 番目の辞書ではすべての要素が削除されます。
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   System.out.println(passportsAndNames.size());
   passportsAndNames.clear();
   System.out.println(passportsAndNames);

}
出力: 3 {} HashMap に少なくとも 1 つの要素があるかどうかを確認するには、次のメソッドを使用できますisEmpty()
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   if (!passportsAndNames.isEmpty()) {

       System.out.println(passportsAndNames);

   }

}
出力: {212133=Lidiya Arkadyevna Bublikova, 8082771=Donald John Trump, 162348=Ivan Mikhailovich Serebryakov} ここでは、事前検証後にのみコンソールに出力します :)

2 つのマップを 1 つに結合する

もう 1 つの興味深い点は、2 つのマップを 1 つに結合できることです。これには方法がありますputAll()最初のHashMapでこれを呼び出し、2 番目の HashMap を引数として渡すと、2 番目の要素が最初の HashMap に追加されます。
public static void main(String[] args) {

   HashMap<Integer, String> passportsAndNames = new HashMap<>();
   HashMap<Integer, String> passportsAndNames2 = new HashMap<>();

   passportsAndNames.put(212133, "Lydia Arkadievna Bublikova");
   passportsAndNames.put(162348, "Ivan Mikhailovich Serebryakov");
   passportsAndNames.put(8082771, "Donald John Trump");

   passportsAndNames2.put(917352, "Alexey Andreevich Ermakov");
   passportsAndNames2.put(925648, "Maxim Olegovich Arkharov");


   passportsAndNames.putAll(passportsAndNames2);
   System.out.println(passportsAndNames);

}
出力: {917352=Alexey Andreevich Ermakov、212133=Lidiya Arkadyevna Bublikova、8082771=Donald John Trump、925648=Maxim Olegovich Arkharov、162348=Ivan Mikhailovich Serebryakov} PassportsAndNames2 のすべての要素がPassportsAndNamesにコピーされました。次に、より複雑な例を見てみましょう。つまり、ループ内で HashMap を反復処理します。
for (Map.Entry entry: passportsAndNames.entrySet()) {

   System.out.println(entry);

}
インターフェイスとは、Map.Entryディクショナリ内のキーと値のペアを意味します。このメソッドは、entrySet()HashMap 内のすべてのペアのリストを返します (マップはまさにそのようなエントリ ペアで構成されているため、個別にキーや値を作成するのではなく、ペアを反復処理します)。結論: 212133=リディヤ・アルカディエフナ・ブブリコワ 8082771=ドナルド・ジョン・トランプ 162348=イワン・ミハイロヴィチ・セレブリャコフ この記事は将来のために保存してください: https://habr.com/ru/post/128017/ 今読むには時期尚早ですが、将来的にはHashMap を実際に使ってみると、このデータ構造が内部からどのように機能するかを理解するのに役立ちます。また、HashMap に関するOracle の公式ドキュメントも忘れずにチェックしてください。
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION