学习笔记
java
jdk
与jre
JDK
是java开发工具包,提供了java的开发环境和运行环境
JRE
是java的运行时环境,提供了java的运行环境
JDK
包含了JRE
,还包含了编译java源码的编译器javac
,还包含了很多java程序调试和分析的工具。- 运行java -> 仅需
JRE
编写java ->JDK
==
和equals
的区别
-
==
对于基本类型来说是值比较,对于引用类型来说是比较的引用 -
equals
默认情况下是引用比较,只是很多类都重写了equals
方法,比如String
Integer
等 将其变成了值比较,所以一般情况下equals
比较的是值是否相等
//String中的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;
}
hashCode()
hashCode()
相同的,equals()
不一定相同
例如,String的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()
返回值是相等的
String str1 = "通话";
String str2 = "重地";
System.out.println(String.format("str1:%d | str2:%d",
str1.hashCode(),str2.hashCode()));
System.out.println(str1.equals(str2));
PS:String.format()
第一个参数是模式串,后面是依次传入的参数,返回值是用前面模式串替换了后面参数的字符串。模式串要替换的数据与C类似,这里%d
是整数的意思,源码如下:
public static String format(String format, Object... args) {
return new Formatter().format(format, args).toString();
}
把元素往set中添加时,首先会对比hashcode
是否相等,如果hashcode
不相等就直接往set中加这个元素,如果hashcode
相等就对比equals方法,如果equals不相等就往set中加这个元素,所以set的元素重复性是根据hashcode
和equals
方法来判断的
同理,当我们自定义两个对象集合中的对象是否相等时,需要重写equals
和hashCode()
方法:
public static void main(String[] args) {
Set<Person> personSet1 = new HashSet<>();
Set<Person> personSet2 = new HashSet<>();
personSet1.add(new Person(1,1));
personSet1.add(new Person(2,1));
personSet2.add(new Person(1,1));
personSet2.add(new Person(1,2));
//返回false
System.out.println(personSet1.equals(personSet2));
}
static class Person{
int age;
int id;
public Person(int age,int id){
this.age = age;
this.id = id;
}
@Override
public boolean equals(Object o){
if(!(o instanceof Person)){
return false;
}
return age == ((Person) o).age && id == ((Person) o).id;
}
@Override
public int hashCode(){
return 0;
}
}
PS:常用hashCode()
计算公式:
@Override
public int hashCode() {
//设置初始值
int result = 17;
//假设有效域为: name,age,idCardNo,incomeAnnual,sex,brithDay
int c = 0;
//计算name (String为对象类型,他的计算直接调用本身的hashCode)
c = name.hashCode();
result = result * 37 + c;
//计算age (int/byte/char/short类型,他的计算直接调用本身的值)
c = this.getAge();
result = result * 37 + c;
//计算idCardNo (long类型,他的计算 (int)(field^(field >>> 32)) 无符号右移32位)
c = (int) (this.idCardNo ^ (this.idCardNo >>> 32));
result = result * 37 + c;
//计算 incomeAnnual (double类型,他的计算 Double.doubleToLongBits(field)后,再按Long类型计算 )
//(float类型,他的计算 Float.floatToIntBits(field) )
long tmp = Double.doubleToLongBits(this.incomeAnnual);
c = (int) (tmp ^ (tmp >>> 32));
result = result * 37 + c;
//计算 sex (sex为boolean类型,他的计算直接调用 c=sex?1:0)
c = this.isSex() ? 1 : 0;
result = result * 37 + c;
//计算 brithDay (brithDay为Date对象类型,他的计算直接调用 本身的hashCode)
c = this.getBirthDay().hashCode();
result = result * 37 + c;
return result;
}