一、hashcode和equals必须同时在类中重写(让equals方法和hashCode方法始终在逻辑上保持一致性)
import java.util.HashMap;
class Dog {
private String name;
private Integer age;
public Dog(){}
public Dog(String name, Integer age) {
this.name = name;
this.age = age;
}
//重写hashCode方法,比较hash值(hash值是哈希表中的数据)
//哈希表是一种数据结构,它提供了快速的插入操作和查找操作。其基于数组来实现。
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
//重写equals方法
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Dog other = (Dog) obj;
if (age == null) {
if (other.age != null)
return false;
} else if (!age.equals(other.age))
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
}
public class HashCodeAndEqualsInfo{
/**
* 测试
* 对于两个对象,如果调用equals方法得到的结果为true,则两个对象的hashcode值必定相等;
* 如果equals方法得到的结果为false,则两个对象的hashcode值不一定不同;
* 但是
* 如果两个对象的hashcode值不等, 则equals方法得到的结果必定为false;
* 如果两个对象的hashcode值相等, 则equals方法得到的结果未知
*
*/
public static void main(String args[]){
/**
* 在HashSet、HashMap以及HashTable插入操作中,类中数据如果是String类型,一定需要实现hashCode和equals方法
*/
Dog dog = new Dog("Marry", 22);
System.out.println("hashCode:"+dog.hashCode());
HashMap<Dog, Integer> hashMap = new HashMap<Dog, Integer>();
hashMap.put(dog, 36);
//如果没有重写hashCode或者equals方法,那么打印null而不是36;
/**原因是没有重写hashCode方法,那么会认为name和age是指向同一个地址即hash值是:33311724
* 如果重写了hashCode和equals方法,那么打印结果是:74115696
*/
System.out.println("结果:"+hashMap.get(new Dog("Marry", 22)));
}
}
二、compareTo方法和compare的意义及作用
1、普通的类要实现排序,必须实现Comparable接口,并重写CompareTo()方法。
2、compareTo(Object o)方法是java.lang.Comparable<T>接口中的方法,当需要对某个类的对象进行排序时,
该类需要实现Comparable<T>接口的,
必须重写public int compareTo(T o)方法,比如MapReduce中Map函数和Reduce函数处理的 <key,value>,
其中需要根据key对键值对进行排序,
所以,key实现了WritableComparable<T>接口,实现这个接口可同时用于序列化和反序列化。
WritableComparable<T>接口 (用于序列化和反序列化)是Writable接口和Comparable<T>接口的组合;
3、compare(Object o1,Object o2)方法是java.util.Comparator<T>接口的方法,它实际上用的是待比较对象的compareTo(Object o)
举例说明:
新建一个Cat.java类
package com.util.compare;
public class Cat implements Comparable<Object>{
int id; //id
String name; //name
public Cat(int id,String name){
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 重写compareTo方法
*/
@Override
public int compareTo(Object o) {
if(this ==o){
return 0;
}
else if (o!=null && o instanceof Cat) {
Cat u = (Cat) o;
if(id<=u.id){
return -1;
}else{
return 1;
}
}else{
return -1;
}
}
}
新建一个测试类:TestClass.java
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class TestClass {
//编写Comparator,根据Cat的id对Cat进行排序
private static final Comparator<Cat> COMPARATOR = new Comparator<Cat>() {
public int compare(Cat o1, Cat o2) {
return o1.compareTo(o2);//运用Cat类的compareTo方法比较两个对象
}
};
public static void main(String[] args) {
ArrayList<Cat> cat = new ArrayList<Cat>();
Cat c1 = new Cat(1,"xiaohei");
Cat c2 = new Cat(2,"xiaohei");
cat.add(c1);
cat.add(c2);
Collections.sort(cat, COMPARATOR);//使用我们写好的Comparator对cat进行排序
//如果是数组排序则使用:Arrays.sort(数组名);
for(int i=0;i<cat.size();i++){
System.out.println("结果:"+cat.get(i).getId());
}
}
}
三、单独使用CompareTo方法
@Test
public void testCpm(){
/**compareTo()的返回值是整型,它是先比较对应字符的大小(ASCII码顺序),
* 如果第一个字符和参数的第一个字符不等,结束比较,返回他们之间的差值
* 如果第一个字符和参数的第一个字符相等,则以第二个字符和参数的第二个字符做比较,
* 以此类推,直至比较的字符或被比较的字符有一方全都比较完,这时就比较字符的长度.
* 结论:compareTo比较一定要比较出差值!
* 如果字符串的ascll都比较完,但str和mes中的每一个字符还是相等,
* 那么就比较字符串长度的差值(如str6和mes6比较)
*/
String str="a"; String mes="b";
String str2="abc"; String mes2="a";
String str3="abdc"; String mes3="2d";
String str4="abcde"; String mes4="ab";
String str5="acd"; String mes5="2br";
String str6="acd"; String mes6="acd";
/**a的ascll码是97,1的ascll码是49*/
System.out.println("结果一:"+str.compareTo(mes)); //-1
System.out.println("结果二:"+str2.compareTo(mes2)); //2
System.out.println("结果三:"+str3.compareTo(mes3)); //47
System.out.println("结果四:"+str4.compareTo(mes4)); //3
System.out.println("结果五:"+str5.compareTo(mes5)); //47
System.out.println("结果六:"+str6.compareTo(mes6)); //0
}