web-dev-qa-db-ja.com

HashMapに空の値または空の値を持つキーとしてデータを保存することをお勧めしますか?

私はもともとArrayListを記述し、その中に一意の値(ユーザー名、つまりStrings)を保存していました。その後、ArrayListを使用して、ユーザーが存在するかどうかを検索する必要がありました。これが検索用のO(n)です。

私の技術リーダーは、それをHashMapに変更し、ユーザー名を配列のキーとして、値を空のStringsとして保存することを望んでいました。

したがって、Java-

_hashmap.put("johndoe","");
_

後で実行すると、このユーザーが存在するかどうかを確認できます-

_hashmap.containsKey("johndoe"); 
_

これはO(1)ですよね?

私のリードは、これはこれを行うためのより効率的な方法であり、私には理にかなっていると言いましたが、ハッシュマップの値としてnull/emptyを入れ、その中に要素をキーとして格納するのは少し外れたようです。

私の質問は、これは良いアプローチですか?一般に、効率は_ArrayList#contains_または配列検索よりも優れています。できます。私の心配は、検索後に他の誰かがこれを行うのを見たことがないということです。どこかで明らかな問題を見逃しているかもしれませんが、それを見ることができません。

63
dozer

一意の値のセットがあるため、Setが適切なデータ構造です。 HashSetインターフェースの実装であるSet内に値を入れることができます。

私のリードは、これはこれを行うためのより効率的な方法であり、私には理にかなっていると言いましたが、ハッシュマップの値としてnull/emptyを入れ、その中に要素をキーとして格納するのは少し外れたようです。

リードのアドバイスに欠陥があります。 Mapはこのための正しい抽象化ではありません、Setはそうです。 Mapは、キーと値のペアに適しています。ただし、値はなく、キーだけがあります。

使用例:

Set<String> users = new HashSet<>(Arrays.asList("Alice", "Bob"));

System.out.println(users.contains("Alice"));
// -> prints true

System.out.println(users.contains("Jack"));
// -> prints false

Mapを使用するのは厄介でしょう。なぜなら、値の型はどうあるべきなのでしょうか?キーと値のペアではなくキーだけを持っているため、その質問はユースケースでは意味がありません。 Setを使用すると、それを尋ねる必要はありません。使用法は完全に自然です。

これはO(1) right?

はい、HashMapまたはHashSetでの検索はO(1)償却された最悪の場合ですが、Listまたは配列での検索中ですO(n)最悪の場合。


HashSetHashMapの観点から実装されていることを指摘するコメントもあります。 そのレベルの抽象化で。手元のタスクの抽象化レベルでは、一意のユーザー名のコレクションを保存するために、セットを使用するのは自然な選択であり、マップよりも自然です。

102
janos

これは基本的にHashSetがどのように実装されるかですので、良いアプローチだと言えると思います。空の値を持つHashSetの代わりにHashMapを使用することもできます。

例えば ​​:

HashSetaddの実装は

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

ここで、mapはバッキングHashMapであり、PRESENTはダミー値です。

私の心配は、検索後に他の誰かがこれを行うのを見たことがないということです。どこかで明らかな問題を見逃しているかもしれませんが、それを見ることができません。

前述したように、JDKの開発者はこの同じアプローチを使用しています。

37
Eran