Java中的equlas函数,默认是比较内存地址,即==;可以重写该函数,可以比较值!
https://www.cnblogs.com/dolphin0520/p/3592500.html
String类对equals方法进行了重写,用来比较指向的字符串对象所存储的字符串是否相等。
其他的一些类诸如Double,Date,Integer等,都对equals方法进行了重写用来比较指向的对象所存储的内容是否相等。
总结来说:
1)对于==,如果作用于基本数据类型的变量,则直接比较其存储的 “值”是否相等;
如果作用于引用类型的变量,则比较的是所指向的对象的地址
2)对于equals方法,注意:equals方法不能作用于基本数据类型的变量
如果没有对equals方法进行重写,则比较的是引用类型的变量所指向的对象的地址;
诸如String、Date等类对equals方法进行了重写的话,比较的是所指向的对象的内容。
String的equals和hashCode函数
https://www.cnblogs.com/weilu2/p/java_hashcode_equals.html
String类的hashCode()方法和equals()方法
hashCode方法
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
使用hashCode()方法确定元素在数据结构中存放的位置
equals()方法
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
可以发现对于String类来说,如果要判断两个String的实例相同,需要逐一判断这两个字符串中的字符是否相同。
HashSet的特别说明:
在HashSet前面的属性声明中可以看到这样一行代码,根据这个我们看出来实际上Java中的HashSet是依托于HashMap的实现的。那么接下来到HashMap中去找这个添加元素的方法看看:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
这里真正存放元素的逻辑是在putVal()这个方法中,这里面代码较多就不贴上来了,这里简述一下其中的关键逻辑。它会调用存入元素的hashCode()方法,计算出元素所对应在表中的位置,然后判断这个位置上是否已经有内容了。如果这个位置上以及有了一个元素,那么就调用传入元素的equals()方法与已有的元素进行对比,以此来判断两个元素是否相同,如果不相同,就将这个元素也存入表中。
代码示例来验证
1、测试所需的User类
public class User {
private String id;
private String name;
private String pwd;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
public User(String id, String name, String pwd) {
super();
this.id = id;
this.name = name;
this.pwd = pwd;
}
public User() {
super();
}
@Override
public boolean equals(Object obj) {
if(this == obj) {
return true;
}
boolean ret = false;
if(this != null && obj != null && obj instanceof User) {
User that = (User)obj;
if(this.id.equals(that.getId())
&& this.name.equals(that.getName())
&& this.pwd.equals(that.getPwd())) {
ret = true;
}
}
return ret;
}
@Override
public int hashCode() {
int hash = 0;
StringBuilder sb = new StringBuilder();
sb.append(id);
sb.append(name);
sb.append(pwd);
char[] charArr = sb.toString().toCharArray();
for(char c : charArr) {
hash = hash * 131 + c;
}
return hash;
}
}
2、Equals&HashCode测试类
import java.text.SimpleDateFormat;
import java.util.Date;
public class EqulasTest {
public static void main(String[] args) throws Exception {
String str1 = "hello";
String str2 = "hello";
System.err.println(str1 == str2); // true -> 比较内容
System.err.println(str1.equals(str2)); // true ->比较内容
System.err.println("hello" == "hello"); // true ->地址相同
Integer obj1 = new Integer(1);
Integer obj2 = new Integer(1);
Integer obj3 = obj1;
System.err.println(obj1 == obj2); // false ->内存地址不同
System.err.println(obj1 == obj3); // true ->内存地址相同
System.err.println(obj1.equals(obj2)); // true ->值相同
System.err.println(obj2.equals(obj3)); // true ->值相同
String dateStr = "2019-04-29 08:08:08";
/*
* Date date = strToDate(dateStr, ""); Date date1 = strToDate(dateStr, "");
* System.err.println(date == date1); // false ->内存地址不同
* System.err.println(date.equals(date1)); // true ->值相同
* System.err.println(date.compareTo(date1)); // true ->值相同
*/
User user1 = new User("1", "lisan", "112233");
User user2 = new User("1", "lisan", "112233");
User user3 = new User("2", "lisan", "112233");
User user4 = user1;
// 未重写User类的equals函数之前
System.err.println(user1 == user2); // false -> 比较内存地址
System.err.println(user1.equals(user2)); // false -> 依然比较内存地址
System.err.println(user1.hashCode()+"=>"+user2.hashCode()); // 366712642=>1829164700
// 重写User类的equals函数之后
System.err.println("User类的equals重写之后=>" + (user1 == user2)); // false -> 比较内存地址
System.err.println("User类的equals重写之后=>" + user1.equals(user2)); // true -> 由于重写之后比较的是对象的各个元素值
System.err.println( "User类的equals重写之后=>" + (user1.hashCode()+"=>"+user2.hashCode())); // 366712642=>1829164700
// 重写User类的hashCode函数之后
System.err.println( "User类的hashCode重写之后=>" + (user1.hashCode()+"=>"+user2.hashCode())); // 1432200454=>1432200454,相当于比较值了
}
/**
* `字符串格式化为时间
* @param src 源字符串
* @param format 格式化,如"yyyy-MM-dd HH:mm:ss";若为空,则使用默认格式化
* @return
*/
public static Date strToDate(String src, String format) {
Date dest = null;
src = trimNull(src);
if (!"".equals(src)) {
format = trimNull(format,DEFAULT_FORMAT);
try {
dest = new SimpleDateFormat(format).parse(src);
} catch (Exception e) {
e.printStackTrace();
}
}
return dest;
}
/**
* 去除空格(若为null或"null"则替换为默认字符串)
* @param src 源字符串
* @param def 默认字符串
* @return
*/
public static String trimNull(String src, String def) {
src = src == null ? "" : src.trim();
return src.toLowerCase().equals("null") ? "" : def;
}
/**
* 去除空格(若为null或"null"则替换为"")
* @param src
* @return
*/
public static String trimNull(String src) {
return trimNull(src, "");
}
/**
* `时间格式化 默认(年-月-日 时:分:秒) yyyy-MM-dd HH:mm:ss
*/
public static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";
}