简单问题:下面的Java程序的输出 公共类abc1{ 私有字符串; 公共abc1(字符串s){this.s=s;} 公共静态void main(字符串参数[]) { HashSet hs=新的HashSet(); abc1 a1=新的abc1(“abc”); abc1 a2=新的abc1(“abc”); 字符串s1=新字符串(“abc”); 字符串s2=新字符串(“abc”); hs.添加(a1); hs.加入(a2); hs.加入(s1); 加上(s2); System.out.println(hs.size()); } }

简单问题:下面的Java程序的输出 公共类abc1{ 私有字符串; 公共abc1(字符串s){this.s=s;} 公共静态void main(字符串参数[]) { HashSet hs=新的HashSet(); abc1 a1=新的abc1(“abc”); abc1 a2=新的abc1(“abc”); 字符串s1=新字符串(“abc”); 字符串s2=新字符串(“abc”); hs.添加(a1); hs.加入(a2); hs.加入(s1); 加上(s2); System.out.println(hs.size()); } },java,equality,hashset,Java,Equality,Hashset,为什么上面的程序输出是3 编辑 看到下面的评论,我扩展了我的问题: System.out.println(s1==s2) s1和s2是指同一个对象吗?如果是,则上述语句应打印为true,但其输出为false 它们在hashcode方面是否相似但仍然不同?有两个不同的abc1(请注意,它不会覆盖equals或hashcode)实例和集合中的一个字符串。让我们看看四个add调用: public class abc1 { private String s; public abc1(String

为什么上面的程序输出是3

编辑

看到下面的评论,我扩展了我的问题:

System.out.println(s1==s2)

s1和s2是指同一个对象吗?如果是,则上述语句应打印为true,但其输出为false


它们在hashcode方面是否相似但仍然不同?

有两个不同的
abc1
(请注意,它不会覆盖
equals
hashcode
)实例和集合中的一个字符串。让我们看看四个
add
调用:

public class abc1 {

 private String s;

 public abc1(String s){this.s=s;}
 public static void main(String args[])
 {
  HashSet<Object> hs=new HashSet<Object>();
  abc1 a1= new abc1("abc");
  abc1 a2= new abc1("abc");
  String s1= new String("abc");
  String s2= new String("abc");
  hs.add(a1);
  hs.add(a2);
  hs.add(s1);
  hs.add(s2);
  System.out.println(hs.size());

 }
}
最初,集合是空的-因此很明显,这将增加值

hs.add(a1);
这也会将值添加到集合中,因为它们是不同的对象,
equals
/
hashCode
的默认实现基本上是引用标识

hs.add(a2);
这将向集合中添加值,因为字符串不等于当前值(不是字符串)

这不会向集合中添加任何内容,因为第二个字符串等于第一个字符串。(字符串重写
等于
/
hashCode


结果是一个集合,其中包含三个项。

,因为您要添加三个唯一的对象——两个abc1对象(必须实现equals和hashCode方法来定义相等)和一个字符串(仅添加一个,因为它实现了这些方法,并且字符串对象中比较的数据相等).

问题是:

hs.add(s2);
您可以尝试执行以下操作:

String s1= new String("abc");
String s2= new String("abc");

您会看到
true
。集合不能包含相同的对象,这就是为什么只有s2存储在那里。

HashSet实现集合接口:

System.out.println (s1 == s2);
公共接口集扩展集合
发件人:

不包含重复元素的集合。更正式地说,集合不包含e1和e2元素对,因此e1.equals(e2)最多包含一个空元素。正如它的名字所暗示的,这个接口为数学集合抽象建模

答复:


我相信s1和s2是相等的,两者不能包含在集合中。无法确定abc1对象是否“相等”。因此,两者都被添加了。

简短的回答是:因为哈希集就像一个,根据定义,它只保存不同的(唯一的)对象。正如其他人在这里所说的,您输入的两个对象显然没有被评估为彼此不同。

Set接口不允许重复元素。这就是您将3作为输出的原因

public interface Set<E> extends Collection<E>

尽管上面创建了两个对象,但它们是相同的元素。

因为
集合
结构(注意你的hashmap是如何被集合支持的)不允许存储两个相等的对象。这就是布景的表现

现在,您可能会被愚弄到认为
a1
a2
都是相等的,但是如果它们不覆盖
equals
hashCode
,那么对于Java,它们就不相等。但是,对于字符串
s1
s2
,它们实际上是相等的,因为字符串实现已经覆盖了
equals
hashCode
方法。尝试执行
s1.equals(s2)
,结果将是
true
。如果你做了
a1.equals(a2)
你会得到
false

最后,哈希集包含a1、a2和s1

你扩展了你的问题,所以要回答

s1
s2
指同一个对象,它们是两个不同的字符串对象,但都代表同一组字符。由于它们不是同一个对象,
System.out.println(s1==s2)
打印
false
。它们是相等的,但不是同一个对象。

给定

String s1= new String("abc");
  String s2= new String("abc");
a1!=a2,因为您没有提供重写的
equals()
,如果a1和a2所包含的字符串相同,则该重写的
equals()将声明a1和a2相同

…和


HashSet
将只保存唯一的对象。

使用“code”按钮格式化代码,这在眼睛里更容易。@leonbloy谢谢。..nxt时间我会的。即使在正确的设置之后仍然存在问题-只存储a1、a2和s1。此外,您的输出代码仍将输出false,因为==检查引用相等,而不是对象相等。@Jon Skeet:这也是一个打字错误)我只是复制了错误的代码块,然后使用了它的变量名。
System.out.println(s1==s2)将打印
false
。哈希集认为
s1
s2
相同的原因是在
String
上实现了
hashCode
s1
s2
不是同一个对象,但是它们重写的equals&hashcode方法意味着相等。@Bill:我相信s1!=s2,所以它们不是同一个实例。之所以只添加一个,是因为HashSet使用equals,字符串覆盖equals,而abc不覆盖。
String s1= new String("abc");
  String s2= new String("abc");
  abc1 a1= new abc1("abc");
  abc1 a2= new abc1("abc");