[Java基础]-- hashcode、equals和compareTo、compare方法的意义及作用

一、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
    }

 

 

 

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要重写equalshashCode方法,需要在类中重写这两个方法。以下是一个示例代码,其中假设有一个名为Person的类,其中包含age和name属性。 ``` import java.util.Objects; public class Person { private int age; private String name; // 构造函数等其他成员变量和方法省略 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(age, name); } // 比较年龄升序,年龄相同时比较英文姓名升序 public int compareTo(Person otherPerson) { int result = Integer.compare(this.age, otherPerson.age); if (result == 0) { result = this.name.compareTo(otherPerson.name); } return result; } // toString方法 @Override public String toString() { return "Person{" + "age=" + age + ", name='" + name + '\'' + '}'; } } ``` 在equals方法中,我们比较了两个Person对象的age和name属性是否相等。在hashCode方法中,我们使用了Objects类的hash方法来生成hashCode。对于比较年龄和英文姓名,我们在类中添加了一个compareTo方法,其中比较了两个Person对象的age和name属性,如果当前对象的age小于otherPerson对象的age,则返回-1,如果当前对象的age大于otherPerson对象的age,则返回1,如果当前对象的age等于otherPerson对象的age,则比较name属性。最后,我们在类中添加了toString方法,用于将Person对象转换为字符串输出。 示例代码中,可以通过以下方式将Person对象按照年龄升序,年龄相同时按照英文姓名升序排列: ``` List<Person> personList = new ArrayList<>(); personList.add(new Person(25, "Tom")); personList.add(new Person(18, "Bob")); personList.add(new Person(18, "Adam")); Collections.sort(personList); System.out.println(personList); ``` 输出: ``` [Person{age=18, name='Adam'}, Person{age=18, name='Bob'}, Person{age=25, name='Tom'}] ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

往事随风ing

你的鼓励将是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值