equals和==的区别是啥?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了equals和==的区别是啥?相关的知识,希望对你有一定的参考价值。
解释一下==号,他比较的是一个对象在内存中的地址值,比如2个字符串对象
String s1 = new String("str");
String s2 = new String("str");
如果用==号比较,会返回false,因为创建了两个对象,他们在内存中地址的位置是不一样的。
equals的情况比较复杂,它是java.lang.Object类中的一个方法。因为java中所有的类都默认继承于Object,所以所有的类都有这个方法。
在Object类源码中是这样写的。
public boolean equals(Object obj)
return (this == obj);
他同样使用==号进行内存地址的比较。但是许多java类中都重写了这个方法,比如String。
public boolean equals(Object anObject)
if (this == anObject)
return true;
if (anObject instanceof String)
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count)
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0)
if (v1[i++] != v2[j++])
return false;
return true;
return false;
String里的方法,如果==号比较不相等,还会进行一下值的比较。
所以equals方法具体的作用要看当前的那个类是如何实现重写父类中该方法的。如果没有重写该方法,那么他和==号等价。 参考技术A “==”是关系运算符,equals()是方法,同时他们的结果都返回布尔值;
“==”使用情况如下:
1) 基本类型,比较的是值
2) 引用类型,比较的是地址
3) 不能比较没有父子关系的两个对象
equals()方法使用如下:
1) 系统类一般已经覆盖了equals(),比较的是内容。
2) 用户自定义类如果没有覆盖equals(),将调用父类的equals (比如是Object),而Object的equals的比较是地址(return (this == obj);)
3) 用户自定义类需要覆盖父类的equals()
注意:Object的==和equals比较的都是地址,作用相同
IEqualityComparer 实现中 GetHashCode 和 Equals 之间的关系是啥? [复制]
【中文标题】IEqualityComparer 实现中 GetHashCode 和 Equals 之间的关系是啥? [复制]【英文标题】:What's the relation between GetHashCode and Equals in a IEqualityComparer implementation? [duplicate]IEqualityComparer 实现中 GetHashCode 和 Equals 之间的关系是什么? [复制] 【发布时间】:2014-04-08 07:48:14 【问题描述】:我有一个继承自 B 类并实现 IEqualityComparer<A>
的类 A。
这意味着 A 类提供了自己的 Equals 和 GetHashCode 方法的实现。到目前为止,一切都很好。
问题是我不明白为什么代码的行为方式如下:
只有当 A 的 GetHashCode 实现返回时,调试器才会到达 A 的 Equals 实现断点
this.GetHashCode()
而不是
obj.GetHashCode()
,其中“obj”是 GetHashCode 的签名定义的参数(在我的例子中是 A 类型的变量)。
直觉上,我认为我应该返回收到的对象的哈希码,但这样做会使编译器忽略实例的 Equals 实现。
为什么会这样?
代码演示:
public class A : B, IEqualityComparer<A>
public bool Equals(A x, A y)
//my implementation...
public int GetHashCode(A obj)
//return obj.GetHashCode(); -> this makes my Equals implementation above be ignored! Why?
return this.GetHashCode(); -> my Equals implementation is used
【问题讨论】:
你能贴一些代码来解释这个问题吗,很难猜对 【参考方案1】:听起来您使用了错误的界面。 IEqualityComparer<>
通常用于比较其他类型实例的类。
你的类型应该简单地实现IEquatable<A>
和覆盖Equals(object)
和GetHashCode()
。注意签名。
像这样:
public class A : B, IEquatable<A>
public bool Equals(A other)
if (other == null || GetType() != other.GetType())
return false;
//your implementation
public override bool Equals(object obj)
return Equals(obj as A);
public override int GetHashCode()
//your implementation
然后您可以执行someEnumerableOfA.Distinct()
之类的操作,Linq 方法将使用您的实现。
另一种选择是:
public class A : B // no interfaces
public class AEqualComparer : IEqualityComparer<A>
public bool Equals(A x, A y)
//your implementation
public int GetHashCode(A x)
//your implementation
使用此其他选项,您需要someEnumerableOfA.Distinct(new AEqualComparer ())
。
【讨论】:
我选择 IEqualityComparer 的原因是因为我的解决方案依赖于调用 IEnumerable.Distinct(IEqualityComparer)。换句话说,如果我想返回我的集合的不同元素,为什么我不能在这里使用 Distinct 并因此需要提供 IEqualityComparer 实现? OP 实现了正确的接口,但方式错误。有关更多信息,请参阅链接的重复线程。 @Veverke,如果您覆盖Equals
和 GetHashCode
,则无需实现或提供 IEqualityComparer<T>
。
@SriramSakthivel 不同意。你不应该有一个类A
实现IEqualityComparer<A>
。那是滥用。看看String
类。它实现了IEquatable<String>
。但是,还有其他类,例如实现 IEqualityComparer<String>
的 StringComparer
(但不 IEqualityComparer<StringComparer>
)。
@Jodrell:我对 Distinct 的 IEnumerable 调用将如何? variable.Distinct(this) - 当前类在哪里覆盖 Equals 和 GetHashCode?span>
【参考方案2】:
实现IEqualityComparer<T>
不是override
的基本实现GetHashCode
和Equals
。
实现IEqualityComparer<T>
允许您提供实现者的实例作为T
的相等比较器。这是几个 linq 扩展和通用集合构造函数的通用参数。
覆盖Equals
和GetHashCode
会影响对类实例进行相等性测试的方式。利用调用 Equals
和 GetHashCode
的其他实现,例如基本 =
和 !=
运算符和 linq 扩展和通用集合构造函数,您不提供替代 IEqualityComparer<T>
。
这些概念相似,但用途不同,不能部分互换。
让我用一个例子来扩展,
public class A
public string Value1 get; set;
public int Value2 get; set;
public override int GetHashCode()
unchecked
int hash = 17;
hash = (hash * 23) +
StringComparer.Ordinal.GetHashCode(this.Value1);
hash = (hash * 23) + this.Value2;
return hash;
public override bool Equals(object obj)
var a = obj as A;
if (a == null)
return false;
if (a.Value2 != this.Value2)
return false;
return StringComparer.Ordinal.Equals(
a.Value1,
this.Value1);
A
的这个实现正确地覆盖了Equals
和GetHashCode
,这个改变足以保证在调用linq扩展之后
var distinct = aSequneceOfA.Distinct();
distinct
不会包含具有相同Value2
和通常可比较Value1
的任何实例。无需其他接口实现即可实现此目的。
现在,假设在某些情况下我对Value1
的这个序数比较不满意,也许我需要不区分大小写。我可能会实现一个新的相等比较器。
public class AComparerInsensitive : IEqualityComparer<A>
public bool Equals(A x, A y)
if (x == null)
return y == null;
if (y == null)
return false;
if (x.Value2 != y.Value2)
return false;
return StringComparer.CurrentCultureIgnoreCase.Equals(
x.Value1,
y.Value1)
public int GetHashCode(A a)
if (a == null)
return 0;
unchecked
int hash = 17;
hash = (hash * 23) +
StringComparer.CurrentCultureIgnoreCase.GetHashCode(
a.Value1);
hash = (hash * 23) + a.Value2;
return hash;
这将允许我调用 Distinct
的替代重载,
var insensitivelyDistinct = aSequneceOfA.Distinct(
new AComparerInsensitive());
这种重载的不同忽略 A
s 被覆盖 Equals
和 GetHashCode
并使用 AComparerInsensitive
执行比较。
【讨论】:
@Veverke 我希望我的扩展答案能让事情更清楚。以上是关于equals和==的区别是啥?的主要内容,如果未能解决你的问题,请参考以下文章
请问各位大佬这道java的重写equals和重写hashcode方法内部是啥意思呀?
"".equals--双引号的equals是啥意思?跪求解释
Java里的equals和==的区别是否equals是比较内容,==是比较地址的?