为什么在Java映射中没有返回给定值的键的方法?

为什么在Java映射中没有返回给定值的键的方法?,java,dictionary,Java,Dictionary,在中,映射界面具有用于containsKey(对象键)、containsValue(对象值)和get(对象键)的方法。为什么没有方法getKey(对象值)?一旦有了一个方法来查找映射是否包含该值,为什么不能同时返回它? 我知道映射可能包含多个值,但该方法可能返回该值的第一个实例。JavaMap接口设计用于按键高效查找值。 最常用的实现之一是HashMap,它将值放入存储桶中,并提供恒定时间查找(假设值在存储桶中分布良好)。这意味着查找密钥的速度非常快—您可以在固定时间内对密钥进行哈希运算,几乎可

在中,映射界面具有用于
containsKey(对象键)
containsValue(对象值)
get(对象键)
的方法。为什么没有方法
getKey(对象值)
?一旦有了一个方法来查找映射是否包含该值,为什么不能同时返回它?

我知道映射可能包含多个值,但该方法可能返回该值的第一个实例。

Java
Map
接口设计用于按键高效查找值。

最常用的实现之一是
HashMap
,它将值放入存储桶中,并提供恒定时间查找(假设值在存储桶中分布良好)。这意味着查找密钥的速度非常快—您可以在固定时间内对密钥进行哈希运算,几乎可以立即查看是否有匹配的值。但是,为了检查是否存在值,需要遍历所有值

另一个常见的实现是
TreeMap
,在某些情况下,它比
HashMap
更好,因为在某些情况下,键可以轻松排序。树的分支允许快速(尽管
log(n)
,而不是固定时间)查找键。但是,同样,查找值需要遍历树的每个节点,直到找到值为止

如果您需要这种从键到值或从值到键的查找,您应该使用
BiMap
,它基本上是将两个贴图卷成一个对象-一个正向贴图和一个反向贴图。我过去用过的谷歌的番石榴图书馆



更好的问题是“如果Java
Map
接口提供的
containsValue
方法对于大多数实现来说效率很低,那么它为什么会提供这种方法?”但我认为这可能是一个偏离主题的话题,你可以考虑问它。

让我们使用一个实现,使用代码> java。UTI.MAP< /Cord>,就像你使用一个联系人列表一样,无论是在你的工作中还是在你的手机上。 比如说,你想找到你朋友约翰·史密斯的电话号码,这样你就可以给他打电话了。您将有机会按名字或姓氏进行搜索

但是,Java对映射的限制是,所有键的键必须是唯一的,因此,如果您认识John Smith和John Doe,那么最后一个插入到映射中的人将“赢”,并且您将丢失John Smith的数据。默默地

如果您改为输入姓氏(如史密斯),然后将您认识的所有史密斯的值放入列表(约翰、简、威廉、罗伯特、埃米特),您将能够高效安全地找到您要查找的内容,而不会有损坏联系人列表的风险


无法按值搜索的原因是在存储到中时没有明确的唯一性保证。即使是被吹捧为解决您问题的“解决方案”的番石榴,仍然受到键和值之间唯一性的限制,这不是您想要的。更糟糕的是,拥有一个
Map
的结构将是一场噩梦,主要是因为该键可以改变任何人都不想要的


如果您希望能够获得给定值的键,那么您别无选择,只能迭代数据结构的全部内容,这(谢天谢地,或者可怕地,由您选择)这正是
Map.Entry提供的功能-一个可编辑的条目集,您可以对映射中的每个元素进行自己的检查。

Java collections框架并没有实现理论上可以通过提供的类实现的所有功能-某些功能可能需要添加到特定的应用程序中。对于为什么选择一组特性而不是另一组特性,没有完全正确的答案——只有框架的原始设计者知道这一点

不过,在这种情况下,似乎可以推测提供反向(value->key)查找是个坏主意,至少有两个原因。首先,对于开发人员来说,与正向(key->value)查找相比,它不一定效率低下。如果您实际上必须使用迭代来实现它,那么它将很快变得显而易见

第二,尽管OP表示,在多个键映射到同一个值的情况下,反向查找方法可能会返回“第一个”匹配值,但在映射中确实没有“第一个”的可靠概念


不过,归根结底,这都是猜测。

可能是因为这会误导用户,让他们认为实施是有效的。不会的。JDK中的所有映射实现都是单向的。他们按照你的建议去做的唯一方法就是迭代所有的键值对。在任何情况下,这里没有人能明确地回答为什么,因为我们没有设计接口。我们所能提供的只是猜测它是否需要内置?写自己似乎很容易,但如果你真的需要这样的东西,不妨看看番石榴BiMap?相关: