杂记
一 凡是涉及到hash的集合,在添加和判断集合中是否有相同对象时,要考虑可能要从写父类Object中的hashCode()方法,equals方法。
所有的包装类和String类,都重写了hashCode 和 equals ,所有,在hashMap和hashSet中,如果以这些类型作为key的类型,那么就不需要考虑重写的问题,否则,如果是以自定义的类的类型作为key的类型,那么就必须要重写hashCode和equals方法。(看源码)
示例代码:
public class ForTest {
public static void main(String[] args) {
Map<MyKey,Cat> map=new HashMap<MyKey,Cat>();
MyKey k1=new MyKey("tom-1");
map.put(new MyKey("cat1"),new Cat("cat1"));
Cat c=map.get(new MyKey("cat1"));
System.out.println(c);
//这里Map的key值是自定义的类型,如果没重写hashCode 和equals的时候,会输出null,
//也就是map中不存在new MyKey("cat1")对象,重写了才能判断存在该对象,
//原理就是hash集合中的put操作,自己去看代码。
}
}
class Cat{
private String name;
public Cat(String name){
this.name=name;
}
}
class MyKey{
private String name;
private Integer age;
public String getName(){
return name;
}
public void setName(String name){
this.name=name;
}
public MyKey(String name){
super();
this.name=name;
}
//由于集合中的key是自定义类型,因此必须重写这两个方法
//才能得到想要的结果,如果是基本类型的包装类类型,那么就不需要重写,这个是需要看底层代码的。
public int hashCode(){
int nameHash=name==null?0:name.hashCode();
int agehash=age==null ?0 : age.intValue();
return nameHash + agehash;
}
public boolean equals(Object obj){
MyKey key0 =(MyKey)obj;
return name.equals(key0.name) && age == key0.age;
}
}
二 equals 和== 以及list集合中的contains
equals: 比较的是两个对象的内容,(仅对String类型的对象,因为String类型的对象重写了父类的equals方法)。
==:对于基本数据类型,比较的是保存的内容,对于引用数据类型,比较的是对象的地址
(笔记Day190622)
举例1:String st1="abc";
String st2="abc";
st1==st2;//输出是true.
String st3=new String "abc";
String st4=new String "abc"
System.out.println(st3==st4);
System.out.println(st3.equals(st4));
举例2:
public class ForTest {
public static void main(String[] args) {
Person p1=new Person("gtl",2);
Person p2=new Person("gtl",2);
System.out.println(p1==p2);
System.out.println(p1.equals(p2)); //输出false, equals 不是说是指向对象保存内容的吗,那这里为什么跟例1中的equals输出的结果不一样呢,不应该也是true吗??
}
}
class Person{
private String name;
private int age;
public Person(){}
public Person(String name ,int age)
{
this.name=name;
this.age=age;
}
// public boolean equals(Object obj){
// //1 空值判断,如果obj是空的,返回false
// if(obj==null){
// return false;
// }
// //2是不是同一个对象呢,看内存地址是不是相等的,如果是相等的,则一定相等
// if(this==obj){
// return true;
// }
// //判断两个对象是否相等,首先判断是不是同一个类
// //3 用instanceof判断对象是不是某种类型,如果是则执行条件中内容
// if(obj instanceof Person){
// //将对象obj强转成Person类
// Person p=(Person)obj;
// //设置一个标签flag,存放名称是否相等
// boolean nameEqu=false;
// if(p.name==null ){
// if(p.name==null){
// nameEqu=true;
// }else{
// nameEqu=false;
// }
// }else{
// nameEqu=name.equals(p.name);
// }
//
// //age是否相同
// boolean ageEqu=this.age == p.age;
// return nameEqu && ageEqu;
// }
// return false;
// }
回答:千万不要死记硬背说equals比较的是两个对象的内容是否相同,这里仅指的是String类型的对象,那为什么String类型的对象比较的就是对象的内容,而其他类对象调用equals方法就不能比较对象内容了呢??? 通过观察源码可以看到,String类对象重写了父类Object中的equals方法,而我们自己新建的类对象并没有实现这个方法,因此就不能比较。所以,例2中看到,结果输出的两个都为false,因此,要想也实现equals方法,应该重写该方法。
重写部分见上面Person类的注释。
扩展:如果ArrayList中保存的是自己定义的类对象,那么就要注意了,要是判断其中有没有已经保存了一个类对象,这个时候就要重写equals方法。原因解释:ArrayList类对象中有个contains方法,通过看源码就知道,判断一个对象有没有在对象中,就取决于equals,所以对于列表的contains方法,可能要重写equals方法,才能得到正确答案。而hashMap类对象中,键是不会重复的,通过看键存不存在就可以判断键所指的值对象有没有存在。