Java中的equals方法和自定义比较器

Object中的equals()方法默认是按地址比较,而不按内容进行比较,

 public boolean equals(Object obj) {
        return (this == obj);
 }

在String中覆写了Object中的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;
    }

"上帝"Object中equals方法可以被子类重写,然后多态调用,当我们要自定义对象比较时一般要覆写equals方法,比如有Person对象,同姓名同年龄,视为同一个对象,

    public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))
        	return false;
		Person p = (Person)obj;
		return this.name.equals(p.name) && this.age == p.age;
	}    

List集合判断元素是否相同,依据是元素的equals方法。

如果要将自定义对象存入到HashSet中,则要覆写hashCode()和equals():

    public int hashCode()
	{
		//System.out.println(this.name+"....hashCode");
		return name.hashCode()+age*11;
	}

	public boolean equals(Object obj)
	{
		if(!(obj instanceof Person))
			return false;
		Person p = (Person)obj;
		
		//System.out.println(this.name+"....equals..."+p.name);
		return this.name.equals(p.name) && this.age==p.age;
	} 

HashSet:底层数据结构是哈希表。是线程不安全的。不同步。
            HashSet是如何保证元素唯一性的呢?是通过元素的两个方法,hashCode和equals来完成。
            如果元素的HashCode值相同,才会判断equals是否为true。
            如果元素的hashcode值不同,不会调用equals。
注意,对于判断元素是否存在,以及删除等操作,依赖的方法是元素的hashcode和equals方法。


自定义比较器:

当元素自身不具备比较性,或者具备的比较性不是所需要的,这时需要让容器自身具备比较性。
当两种排序都存在时,以比较器为主。
方式1:定义一个类,实现Comparable接口,覆盖compareTo方法。

class Student implements Comparable//该接口强制让学生具备比较性。
{
	private String name;
	private int age;

	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}

	//先按年龄从小到大排序,如果年龄相同,再按名字
	public int compareTo(Object obj)
	{
		if(!(obj instanceof Student))
			throw new RuntimeException("不是学生对象");
		Student s = (Student)obj;
		
		if(this.age>s.age)
			return 1;
		if(this.age==s.age)
		{
			return this.name.compareTo(s.name);
		}
		return -1;		
	}

	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}

class Test 
{
	public static void main(String[] args) 
	{
		TreeSet ts = new TreeSet(new Mycompare());

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi02",21));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi06",18));
		ts.add(new Student("lisi06",18));
		ts.add(new Student("lisi007",29));
		
		Iterator it = ts.iterator();
		while(it.hasNext())
		{
			Student stu = (Student)it.next();
			System.out.println(stu.getName()+"..."+stu.getAge());
		}
	}
}

方式2:定义一个类,还要再自定义一个比较器实现Comparator接口,覆盖compare方法。

定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。

class Student
{
	private String name;
	private int age;

	Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	
	public String getName()
	{
		return name;
	}
	public int getAge()
	{
		return age;
	}
}

//自定义比较器:先按名字来排序,如果名字相同再按年龄
class Mycompare implements Comparator
{
	public int compare(Object o1,Object o2)
	{
		Student s1 = (Student)o1;
		Student s2 = (Student)o2;

		int num = s1.getName().compareTo(s2.getName());
		if (num == 0)
			return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
		return num;
	}
}
class Test 
{
	public static void main(String[] args) 
	{
		TreeSet<Student> ts = new TreeSet<Student>(new Mycompare());

		ts.add(new Student("lisi02",22));
		ts.add(new Student("lisi02",21));
		ts.add(new Student("lisi007",20));
		ts.add(new Student("lisi09",19));
		ts.add(new Student("lisi06",18));
		ts.add(new Student("lisi06",18));
		ts.add(new Student("lisi007",29));
				
		for (Iterator<Student> it = ts.iterator();it.hasNext() ; )
		{
			Student stu = it.next();
			System.out.println(stu.getName()+".."+stu.getAge());
		}
	}
}
原文地址:https://www.cnblogs.com/iadanac/p/3873525.html