java map中containsValue中怎么比较对象是不是相等

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java map中containsValue中怎么比较对象是不是相等相关的知识,希望对你有一定的参考价值。

比如map.containsValue(Student) Student类中有学号、姓名。

我使用时是这样用的map.containsValue(new Student(1,“lili”)),然后老是返回false。是不是它比较的是地址而不是内容啊?

参考技术A 两种方法修正:1.重写map的containsValue方法,匹配你自定义的Student类的所有属性;2.containsValue传入常量(前提是你保存的是常量)。
建议你用第一种方法,了解更多的java源码有利于提升技术追问

我怎么重写这个方法了?先谢过了!

参考技术B 在Student类中覆写hashCode() 和 equalse()方法追问

我现在是准备写一个自己的map类,然后复写那个函数。
是不是您这个更快啊?那我就不用再生成类了。
hashCode()怎么使用?

追答import java.util.HashMap;
import java.util.Map;
public class MapTest 
private final static Object ANY = new Object();
public static void main(String[] args) 
Map<Student, Object> map = new HashMap<Student, Object>();

map.put(new Student(1,"lili"),ANY);
map.put(new Student(11,"lilili"),ANY);
map.put(new Student(111,"lililili"),ANY);

System.out.println(map.containsKey(new Student(1,"lili")));



class Student
private int number;
private String name;
Student(int number, String name)
this.number = number;
this.name = name;

@Override
public boolean equals(Object obj) 
Student stu = (Student) obj;
return this.name.equals(stu.name) && this.number == stu.number;


@Override
public int hashCode() 
return name.hashCode() + number*39;

本回答被提问者采纳
参考技术C 它比较的是地址而非内容追问

我怎么比较里面的内容了?怎么重写方法?

java中HashMap.containsValue()的时间复杂度是多少?

【中文标题】java中HashMap.containsValue()的时间复杂度是多少?【英文标题】:What is the time complexity of HashMap.containsValue() in java? 【发布时间】:2013-05-21 09:02:19 【问题描述】:

O(n) 时间复杂度中给了我一个要解决的问题:

“给定一个数字列表和数字 x。查找列表中是否有 2 个数字加起来为 x?”

这是我的解决方案:

public class SumMatchResult 

  public static void main(String[] args)
    int[] numberList = 6,1,8,7,4,6;
    int requiredSum = 8;
    boolean isSumPresent = checkSumPresentHash(numberList,requiredSum);
    if(isSumPresent) 
      System.out.println("Numbers exist");
    else 
      System.out.println("Numbers donot exist");
    
  

  private static boolean checkSumPresentHash(int[] numberList, int requiredSum) 
    Map<Integer, Integer> m = new HashMap<Integer,Integer>();
    int count = 0;
    for(int i=0;i<numberList.length;i++)
      m.put(i, numberList[i]);
    
    for(int i=0;i<numberList.length;i++)
      if(m.containsValue(requiredSum - numberList[i]))
        count++;
      
    
    if(count>1)
        return true;
    
    return false;
  


我使用HashMap.containsValue() 而不是使用HashSet.contains(),它肯定具有O(1) 的复杂性,因为我必须考虑我的输入可能包含相同值的情况。例如,在上述情况下,我可以有一组输入值3,6,4,4,7sum 8 匹配,它应该返回true

我上述解决方案的时间复杂度取决于HashMap.containsValue() 方法的复杂度。请阐明containsValue() 方法的时间复杂度,并建议我在时间复杂度方面是否有上述问题的更好解决方案。谢谢。

【问题讨论】:

也许你应该使用Set 而不是Map 我很想知道有一种算法可以在 O(n) 时间内解决这个问题。我不确定这是否可能。 保持一个单独的HashMap 与第一个值作为他的键怎么样?这样您就可以立即知道 (O(1)) 是否存在值。这是O(2n) 空间,但嘿,这很值得。 @JBNizet 我上次看到它已经有很长时间了,但这闻起来像是背包问题的(非常)简化版本。动态编程在这里应该有所帮助。 @Bohemian 不,它是关于containsValue(),这是复杂性的根本区别。 【参考方案1】:

要回答标题中的问题 - 正如其他人所提到的,containsValue 是 O(n),因为没有密钥它不知道它在哪里,并且算法必须遍历存储在地图。

要回答问题正文中的问题 - 关于如何解决问题 - 只需考虑您是否真的需要一张通用地图,该地图可以计算您看到每个数字的实例数。我的意思是,唯一你会关心一个数字是否不止一次出现的时候是它的 x/2,对吧?这对我来说就像一个角落里的箱子。只需添加一个检查该极端情况的测试——比如在你的集合构造循环中嵌入if (numberList[i] == requiredSum/2) half++,然后在它之后嵌入if (requiredSum % 2 == 0 &amp;&amp; half == 2) return true(参见下面的其他变体)。

然后你可以遍历集合并为每个项目检查 requiredSum-item 是否也出现在集合中。

总结(尽可能提前退出):

Set<Integer> seen = new HashSet<Integer>();
boolean halfSeen = false;
for (int num : numberList) 
    if (num == requiredSum/2 && requiredSum % 2 == 0) 
        if (halfSeen) return true;
        halfSeen = true;
     else 
        seen.add(num);
    

for (int num : seen) 
    if (seen.contains(requiredSum - num)) return true;

return false;

【讨论】:

+1 关于角盒的好点(if (numberList[i] == requiredSum/2))。很棒的整体解决方案! @Oak :非常感谢您的解决方案。不过稍微修正一下,seen.add(num) 应该在 else 部分,否则,即使只有一个 num ==requiredSum/2,它也会被添加到集合中,并且下一个循环返回 true,这是错误的。 @VishnuVedula 好点,已修复。此更改还需要将除以二的检查移动到封闭的if,因为如果requiredSum 是7,那么我们确实希望在seen 中保留3。【参考方案2】:

HashMap 本质上是一个键值存储,它可以访问它的键,复杂度为 O(1)。然而,检查一个值,HashMap 只能检查所有值并查看它们是否等于您正在搜索的值。因此,复杂度为 O(n),其中 n 为 HashMap 中的元素个数。

另外一点:您在其装箱类型 (Integer) 的集合中查找原始值 (int)。这意味着每次您在 HashMap 上调用方法时,Java 都需要将原始值装箱:http://docs.oracle.com/javase/1.5.0/docs/guide/language/autoboxing.html

【讨论】:

以后一定会记住装箱和拆箱的。谢谢你:)【参考方案3】:

HashMap.containsValue 复杂度为 O(n)。但是 n 不完全是映射大小,而是哈希表大小,因为即使映射大小 = 0, containsValue 也会遍历所有表元素。 假设我们创建了一个初始容量 = 1024 的空映射。 containsValue 必须遍历 1024 个元素的哈希表数组:

public boolean containsValue(Object value) 
    if (value == null)
        return containsNullValue();

    Entry[] tab = table;
    for (int i = 0; i < tab.length ; i++)
        for (Entry e = tab[i] ; e != null ; e = e.next)
            if (value.equals(e.value))
                return true;
    return false;

【讨论】:

【参考方案4】:

HashMap 中没有任何值标记的索引,因此,要使用containsValue() 查找值,您必须遍历HashMap 的所有值。

请注意,这里的复杂度O(n) 是 HashMap 中值的数量,不是我们通常用来表示其复杂度的键/大小。

【讨论】:

以上是关于java map中containsValue中怎么比较对象是不是相等的主要内容,如果未能解决你的问题,请参考以下文章

java中HashMap.containsValue()的时间复杂度是多少?

java 怎么判断一个集合是不是含有某个值

Java中的Map

Java中的Map

JAVA-Map

Map集合总结