zoukankan      html  css  js  c++  java
  • 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());
    		}
    	}
    }
    
  • 相关阅读:
    Windows如何快速远程到另一台Windows并管理多个远程服务器
    基于视觉反馈的步进电机X-Y平台控制
    相机位姿估计3:根据两幅图像的位姿估计结果求某点的世界坐标
    相机位姿估计2:[应用]实时位姿估计与三维重建相机姿态
    相机位姿估计1_1:OpenCV:solvePnP二次封装与性能测试
    求空间内两条直线的最近距离以及最近点的坐标(C++)
    相机位姿估计1:根据四个特征点估计相机姿态
    相机位姿估计0:基本原理之如何解PNP问题
    记2016年中国移动广西公司面试(计算机类)
    子坐标系C在父坐标系W中的旋转问题
  • 原文地址:https://www.cnblogs.com/iadanac/p/3873525.html
Copyright © 2011-2022 走看看