Set集合解析何能进何不能进
Posted Felx_chu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Set集合解析何能进何不能进相关的知识,希望对你有一定的参考价值。
Set集合何能加到集合中,何不能加进去?我们先来看看有什么问题;
有图有真相:
1.
set.add(new People("zhangsan"));
set.add(new People("lisi"));
set.add(new People("zhangsan"));
运行结果:
这个结果的3个地址我们认为:三个People的对象,所以能进三个。
2.
People p1 = new People("zhangsan");
set.add(p1);
set.add(p1);
运行结果:
这个结果我们会认为,两个P1的引用指向同一对象,所以只能进一个。
3.
String s1 = new String("a");
String s2 = new String("a");
set.add(s1);
set.add(s2);
运行结果:
这个结果会使我们解释有点晕,两个new出的String(两个对象),却只能进一次。
为了解决这个问题,我们要查看set的add()方法:
add
boolean add(E e)
如果 set 中尚未存在指定的元素,则添加此元素(可选操作)。更确切地讲,如果此 set 没有包含满足 (e==null ? e2==null : e.equals(e2)) 的元素 e2,则向该 set 中添加指定的元素 e。如果此 set 已经包含该元素,则该调用不改变此 set 并返回 false。结合构造方法上的限制,这就可以确保 set 永远不包含重复的元素。
我们发现里面有equals方法,我们需要继续查看equals方法的源码,在Object类中:
public boolean equals(Object obj)
指示其他某个对象是否与此对象“相等”。
equals 方法在非空对象引用上实现相等关系:
o 自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true。
o 对称性:对于任何非空引用值 x 和 y,当且仅当 y.equals(x) 返回 true 时,x.equals(y) 才应返回 true。
o 传递性:对于任何非空引用值 x、y 和 z,如果 x.equals(y) 返回 true,并且 y.equals(z) 返回 true,那么 x.equals(z) 应返回 true。
o 一致性:对于任何非空引用值 x 和 y,多次调用 x.equals(y) 始终返回 true 或始终返回 false,前提是对象上 equals 比较中所用的信息没有被修改。
o 对于任何非空引用值 x,x.equals(null) 都应返回 false。
Object 类的 equals 方法实现对象上差别可能性最大的相等关系;即,对于任何非空引用值 x 和 y,当且仅当 x 和 y 引用同一个对象时,此方法才返回 true(x == y 具有值 true)。
注意:当此方法被重写时,通常有必要重写 hashCode 方法,以维护 hashCode 方法的常规协定,该协定声明相等对象必须具有相等的哈希码。
我们需要继续查看hashCode方法:
public int hashCode()
返回该对象的哈希码值。支持此方法是为了提高哈希表(例如 java.util.Hashtable 提供的哈希表)的性能。
hashCode 的常规协定是:
o 在 Java 应用程序执行期间,在对同一对象多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是将对象进行 equals 比较时所用的信息没有被修改。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。
o 如果根据 equals(Object) 方法,两个对象是相等的,那么对这两个对象中的每个对象调用 hashCode 方法都必须生成相同的整数结果。
o 如果根据 equals(java.lang.Object) 方法,两个对象不相等,那么对这两个对象中的任一对象上调用 hashCode 方法不 要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
实际上,由 Object 类定义的 hashCode 方法确实会针对不同的对象返回不同的整数。(这一般是通过将该对象的内部地址转换成一个整数来实现的,但是 JavaTM 编程语言不需要这种实现技巧。)
在String方法中重写hashCode方法:
public int hashCode()
返回此字符串的哈希码。String 对象的哈希码根据以下公式计算:
s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
使用 int 算法,这里 s[i] 是字符串的第 i 个字符,n 是字符串的长度,^ 表示求幂。(空字符串的哈希值为 0。)
所以,我们会发现字符串类型,比较的不是地址信息了,比较的是字符串的值,如果两个字符串的内容一样,那么他们的hashCode的值也是一样的。
试验一下:
结果为:
hashCode的值一样;
总结: 当使用 HashSet 时,hashCode()方法就会得到调用,判断已经存储在集合中的对象的hash code 值是否与增加的对象的 hash code 值一致;如果不一致,直接加进去;如果一致,再进行 equals 方法的比较,equals 方法如果返回 true,表示对象已经加进去了,就不会再增加新的对象,否则加进去。
1.圣思园张龙老师的JavaSE视频教程。
以上是关于Set集合解析何能进何不能进的主要内容,如果未能解决你的问题,请参考以下文章