HashMap有containsValue方法,但不是getValue方法

时间:2015-02-06 00:43:22

标签: java collections hashmap java-7

我很好奇,在Java集合库中, HashMap 有一个方法可以搜索名为 containsValue的特定对象值的存在性(对象值) 撤回 布尔 ,但 值对象 strong>通过 值对象 ,直接通过 get(对象键)方法提供。现在,我知道 HashMap 的目的是通过键访问对象值,但在特殊情况下可能需要通过对象值进行检索,那么为什么没有 getValue(对象值)方法?我问这个,因为方法 containsValue() 实现搜索 对象值 的算法更快比我的自定义搜索(见下面)。另外,有没有更好的方法在Java 7中使用 HashMap 完成此搜索?

代码段:

// Custom Search
MyCustomer findCust = new MyCustomer(50000, "Joe Bloggs", "London");
for (MyCustomer value : hashMap.values()) {

    if (value.equals(findCust)) { // found
            cust = value;
            break;
    }

}

3 个答案:

答案 0 :(得分:0)

hashMap.values().contains(findCust)

根据您的"业务规则"您将需要在客户上使用equals和hashCode。 (例如,两个客户具有相同的" id"但是具有不同的其他值"等于" ???? ...显然你已经这样做,因为你使用的是equals。 ..)

答案 1 :(得分:0)

集合框架的基本假设是,如果两个对象是.equals,则它们在各方面都是可互换的。鉴于这种假设,没有理由从Map中获取值,因为您已经拥有equals且可互换的值。就集合框架而言,这两种方法是完全等效的:

for (V value : map.values()) {
  if (value.equals(myValue)) {
    return value;
  }
}

if (map.containsValue(myValue)) {
  return myValue;
}

这个假设在许多地方内置于集合框架中,这是许多例子中的一个。

答案 2 :(得分:0)

HashMap旨在使用您用于将某些值放入地图的键的hashcode()equals()来帮助进行常量查找。

如果你看一下HashMap的内部结构,它只不过是一个数组。每个索引称为一个桶,可以通过规范化当前数组的长度和传递的密钥的哈希码来获得。找到存储桶后,它会将元素存储在该特定索引处。但是如果已经存在一些元素存储在该索引中,它们将形成这些元素的LinkedList,链接具有相同hashcode()但不同equals()条件的所有值。

在Java 8中,如果该链表中的元素数量达到某个阈值(8)以提高性能,则该链表甚至会更改为TreeMap。

回到你的问题,containsValue()基本上遍历数组中的所有桶,并再次遍历每个桶的链表中的所有元素

// iterate through buckets
for (int i = 0; i < table.length; ++i) {

      // iterate through each element in linked list at each bucket
      for (Node<K,V> e = table[i]; e != null; e = e.next) {
              if ((v = e.value) == value ||
                      (value != null && value.equals(v)))
                   return true;
      }
 }

HashMap.values()返回一个Collection,其迭代器实现为遍历HashMap中的每个元素,在每次迭代中提供对Value对象的访问。

containsValue()用于你想要做的事情,如果地图中已有某些值,但你不需要那个值来继续你的流程。这只是一种方便的方法,因为如果你是使用values,您将创建一个Collection对象和一个迭代器对象来迭代它们,但使用containsValue(),您只需要两个嵌套的for循环。我认为没有getValue()的原因是为了鼓励HashMap的目的 - 使用hashcode&amp;和接近恒定的时间查找。等于一些关键。

当你基本上需要遍历所有值时,使用

values()。这与在循环中调用map.get(key)不同,因为您不必标准化哈希码,找到存储桶,然后在每次迭代中找到链表中的元素,只需循环自然顺序,顺便说一下元素在数组中布局。

如果您执行此值查找的次数太多,则会失去HashMap提供的常量查找的优势。如果您只是浏览搜索某些值的值,我建议您使用ArrayList。如果该列表中的元素太多,并且您需要经常搜索某个随机值,请对列表进行排序并使用二进制搜索。