String,重写equals(),hashCode()

一、关于String

String:字符串是不变的;它们的值在创建后无法更改,是线程安全的。 String类主要用于对字符串内容的检索、比较等操作,操作的结果通常得到一个新字符串,但不会改变源串的内容 .

二、主要操作方法

1.构造函数,

新创建的字符串是参数字符串的副本。除非需要original的显式副本,否则使用这个构造函数是不必要的,因为字符串是不可变的。

2.字符串的连接:+

3.字符串的转换:toString()

4.字符串的比较:equals()——将此字符串与指定的对象进行比较。当且仅当参数不是{null},并且是一个代表与此对象相同字符序列的字符串对象,结果是{@code * true}

5.hashCode(),散列值,一般重写equals就重写该方法.
6.compareTo()
7.字符串操作:indexOf()ength(),isEmpty(),charAt(),getChars(),substring(),replace(),matches(),contains(),split(),join(),toLowerCase(),toUpperCase(),trim()
8.startsWith(),endsWith(),可以利用该方法判断前缀和后缀

三、重写equals

Object类是类层次结构的根,即所有类的最终祖先,Java中的类都是Object类的直接或间接子类.

Object类中的equals()方法:



public boolean equals(Object obj) {

    return (this == obj);

}


在定义类时建议重写equals()方法,String中重写的equals()方法:

public boolean equals(Object anObject) {
    if (this == anObject) {		//初始判断与Object中一样
        return true;
    }
    if (anObject instanceof String) {		//判断是否为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;
}

注意:从上面的例子,我们可以总结出重写equals()方法的诀窍:

1).检查是否为这个对象的引用,可以使用”==“操作符检查
2).检查是否为同一个类型,可以使用instanceof操作符,也可以使用getClass()进行判断
3).如果是同一个类型,则对该类的属性进行比较
4).并且在覆盖equals时总要覆盖HashCode()。

四、重写hashCode()

java中创建的对象是保存到堆中的,为了提高查找的速度而使用了散列查找。散列查找的基本思想是定义一个键来映射对象所在的内存地址。当需要查找对象时,直接查找键即可。查看散列码:将重写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;
}

Java中规定,两个内容相同(equals()为true)的对象必须具有相等的hashCode。 因为如果equals为true而两个对象的hashCode不同,那么在整个存储过程中就发生了悖论。

示例代码:

public class EmployeeSimple implements Cloneable {
    private String name;
    private int age;

    public EmployeeSimple() {
    }

    public EmployeeSimple(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
   //省略get,set...
   
    @Override
    public boolean equals(Object obj) {
        //  检查是否为这个对象的引用,可以使用”==“操作符检查
        if (this == obj) //  如果两个员工是同一个对象则相同
            return true;
        // 对于任何非空引用值x,x.equals(null)应该返回false
        if (obj == null)// 如果两个员工有一个为null则不同
            return false;
        //检查是否为同一个类型,可以使用instanceof操作符,也可以使用getClass()进行判断
        if (getClass() != obj.getClass())
            return false;
        EmployeeSimple employee = (EmployeeSimple) obj;
        //对该类的属性进行比较
        return (getName().equals(employee.getName())) && (getAge() == employee.getAge());

    }
   // 并且在覆盖equals时总要覆盖HashCode()。
    @Override
    public int hashCode() {
        return 7 * name.hashCode() + 11 * new Integer(age).hashCode();
    }
    public String toString() {
        return "姓名:" + getName() + ",年龄:" + getAge();
    }
   
}

测试:

public static void main(String[] args) {
    EmployeeSimple employee1 = new EmployeeSimple("张三", 26);
    System.out.println("emp1" + employee1);
    EmployeeSimple employee2 = new EmployeeSimple("张三", 26);
    System.out.println("emp2" + employee2);
    EmployeeSimple employee3 = new EmployeeSimple("李四", 20);
    System.out.println("emp3" + employee3);

    System.out.println("employee1.equals(employee2):" + (employee1.equals(employee2)));
    System.out.println("employee1.equals(employee3):" + (employee1.equals(employee3)));
    System.out.println("emp1 HashCode:"+employee1.hashCode());
    System.out.println("emp2 HashCode:"+employee2.hashCode());
    System.out.println("emp3 HashCode:"+employee3.hashCode());

}

String,重写equals(),hashCode()_第1张图片

你可能感兴趣的:(java)