将数据存储为具有空/空值的HashMap中的键是一个好主意吗?

我最初写了一个并存储了唯一值(用户名,即)。我后来需要使用 来搜索其中是否存在用户。这是为了搜索。ArrayListStringsArrayListO(n)

我的技术主管希望我将其更改为 a,并将用户名作为键存储在数组中,值存储为空。HashMapStrings

所以,在Java中 -

hashmap.put("johndoe","");

我可以通过运行 - 查看此用户以后是否存在 -

hashmap.containsKey("johndoe"); 

这是对的吗?O(1)

我的领导说这是一种更有效的方法,这对我来说是有道理的,但是将null/empty作为哈希图中的值并存储其中的元素作为键似乎有点不对劲。

我的问题是,这是一个好方法吗?效率高于或数组搜索一般。它的工作原理。我担心的是,在搜索后,我还没有看到其他人这样做。我可能在某个地方错过了一个明显的问题,但我看不到它。ArrayList#contains


答案 1

由于您有一组唯一值,因此 a 是适当的数据结构。你可以把你的值放在接口的实现中。SetHashSetSet

我的领导说这是一种更有效的方法,这对我来说是有道理的,但是将null/empty作为哈希图中的值并存储其中的元素作为键似乎有点不对劲。

领导的建议是有缺陷的。 不是正确的抽象这个,是。A 适用于键值对。但是你没有值,只有键。MapSetMap

用法示例:

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

使用 a 会很尴尬,因为值的类型应该是什么?这个问题在你的用例中没有意义,因为你只有键,而不是键值对。使用 ,您不需要问这个问题,用法是完全自然的。MapSet

这是O(1)对吧?

是的,在 a 或 a 中搜索是 O(1) 摊销的最坏情况,而在 a 或数组中搜索是 O(n) 最坏情况。HashMapHashSetList


一些注释指出,a 是按照 .在那个抽象级别上,这很好。在手头任务的抽象级别---存储唯一用户名的集合,使用集合是一种自然的选择,比地图更自然。HashSetHashMap


答案 2

这基本上是如何实现的,所以我想你可以说这是一个好方法。您也可以使用空值代替您的值。HashSetHashSetHashMap

例如:

HashSet的实现是add

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

其中 是后备,是一个虚拟值。mapHashMapPRESENT

我担心的是,在搜索后,我还没有看到其他人这样做。我可能在某个地方错过了一个明显的问题,但我看不到它。

正如我所提到的,JDK的开发人员正在使用相同的方法。