关于hashset,hashmap,hashcode,equals的困惑

时间:2014-11-13 13:39:43

标签: java hashcode hashset scjp

SET的属性是它不允许重复的元素。

但引用SCJP:使用hashset或linkedhashset时。当你添加对象时,你必须覆盖哈希码,否则你可能会在集合中找到重复的元素。

boolean[] b=new boolean[5];
Set s=new HashSet();
b[0]=s.add("a");
b[1]=s.add("a");

此处输出为True,False 我不知道当你没有覆盖哈希码时输出是如何错误的。 但是当你重写hashcode时,你必须重写equals()。

DOes Collection接口是否提供默认的equals()方法?

我无法理解,

5 个答案:

答案 0 :(得分:3)

您正在添加两个java.lang.String类,Sun / Oracle已经为您提供了适合.hashCode().equals()方法的类: - )

注意: 需要equals和hash方法的集合 - 它是您将放入其中的对象!

如果要将YourOwnClass个对象添加到JDK集合中,则必须明智地覆盖这两个方法。考虑一下,其中YourOwnClass回到java.lang.Object的方法实现:

class YourOwnClass
{
    String a;
    public YourOwnClass(String a) { this.a = a; }
}

public void testYourOwnClass() throws Exception
{
    Set<YourOwnClass> set = new HashSet<YourOwnClass>();

    System.out.println( set.add( new YourOwnClass( "b" ) ) );
    System.out.println( set.add( new YourOwnClass( "b" ) ) );
}

这将打印

  

     

尽管我们可以争辩说,从语义角度来看,添加的两个YourOwnClass对象应该被认为是相同的。

然后,按如下所示修改YourOwnClass,然后重试。

class YourOwnClass
{
    String a;
    public YourOwnClass(String a) { this.a = a; }

    @Override public int hashCode() { return a.hashCode(); }
    @Override public boolean equals(Object obj) { return a.equals( ((YourOwnClass)obj).a ); }
}

Voila - 这次是“真假”!

干杯,

答案 1 :(得分:2)

好的..开始吧。

使用hashset或linkedhashset时。 LinkedhashSet维护插入元素的顺序,HashSet不。

我想知道输出是怎么回事 如果添加了元素,则add()方法返回true(当元素不是已经存在于set.So中时,在您的情况下,第一次出现,&#34; a&#34 ;不存在于集合中),因此它第一次返回true。第二次,&#34; a&#34;已经存在,它将返回false。

接下来,默认情况下,所有对象都有hashCode()equals()实现。您必须覆盖它们才能更改默认行为。

答案 2 :(得分:1)

  

Collection接口是否提供默认的equals()方法?

默认情况下是,hashCode()方法用于equals()类本身中定义的Object

对于某些类,例如Stringequals()检查字符是否相等。

检查String.equals()方法的源代码


如果已在Set中添加了项目,则会返回false,否则返回true中提到的{{1}}。

答案 3 :(得分:0)

首先,String会覆盖hashCodeequals,因此您的代码会使用String这些方法的版本(因为您要添加String }到你的HashSet)。

其次,即使它没有,在你的例子中,“a”被实习,因此对s.add(“a”)的两次调用都添加完全相同的对象,所以即使Object <{1}}和hashCode的默认实现会产生相同的结果。

答案 4 :(得分:0)

首先要做的事情 - 我完全同意并且上面有关于LinkedHashset的+1 @TheLostMind回答。此外,您可能缺乏对.add()方法实际返回的理解,即在返回布尔结果之前检查了什么。

P.S。它是JavaBeans中的标准之一,您应该覆盖hashcode()和equals()以避免错误结果 - 请参阅http://www.xyzws.com/javafaq/why-always-override-hashcode-if-overriding-equals/20

请记住,您正在使用HashSet,而对于HashSet,equals()hashCode()方法是从AbstractSet继承的。 AbstractSet是一个抽象类,HashSet扩展它,不需要实现任何抽象方法。因为equals()和hashCode()已经实现,所以您在下面的代码中看到的结果为true和false。我使用范围{}运算符将它们分开以提高清晰度。

public static void main (String[] args) throws java.lang.Exception
{

{   boolean[] b = new boolean[5]; 
    Set s = new HashSet(); 
    b[0]=s.add(new Integer(2)); 
    b[1]=s.add(new Integer(2));

    System.out.println("Using Hashset Integers b0 = "+b[0]+" and b1 = "+b[1]);
}

{   
    boolean[] b=new boolean[5]; 
    Set s=new HashSet(); 
    b[0]=s.add(2); 
    b[1]=s.add(2);
    System.out.println("Using Hashset int b0 = "+b[0]+" and b1 = "+b[1]);
}   


}

我相信intInteger hashCode()和equals()是由Java整理出来的。你不必担心这一点。我使用Spring Framework实现了一个dataserver,我需要自己的实体类,并确保我可以将我的Entity bean对象保存到HashMap中,我必须在我的Entity定义类中重写equals()和hashCode()。如果您使用Eclipse,则可以使用autogenerator为您提供hashCode()和equals()的框架,然后可以根据您的需要对其进行编辑。