• HashSet存储过程中如何排除不同的自定义对象?


    HashSet

    HashSet存储过程中如何排除不同的自定义对象?

    先看一个小demo

    public class Demo1 {
    	public static void main(String[] args) {
    		//Person4类是一个失血模型,它有姓名和年龄两个属性
    		HashSet<Person4> set = new HashSet<>();
    		set.add(new Person4("张三", 23));
    		set.add(new Person4("张三", 23));
    		set.add(new Person4("李四", 24));
    		set.add(new Person4("李四", 24));
    		set.add(new Person4("李四", 24));
    		
    		/*
    		 * 直接打印,我们会发现,它把5个元素加入进去了,包括我们认为“重复”的元素
    		 * 可是,HashSet不是号称不可重复吗?这是为什么?
    		 */
    		System.out.println(set);
    	}
    }
    

    HashSet在存储自定义的对象比如Person4(含name和age属性)时,如果存放name和age值相同的对象时,它都会存放进去。因为我们把它当作是相同的元素是根据它的属性值判断,而程序会为每个new出来的对象计算出不同的hashcode码,所以它认为是不同的对象,都会存放进去。

    如何让它有效排除我们认为的“所有属性值相同的对象就是同一个对象”在这种定义下的同一种对象呢?

    首先我们要去了解它的底层实现,即:
    它判断是否相同的时候,肯定用了equals方法,他在计算hashcode的时候,应该用到了hashCode方法,那么它的执行流程和内部是怎么实现的呢?

    我们追溯HashSet的源码,首先我们用到了add方法,它在add的时候肯定会进行是否存在相同对象的判断。我按住ctrl+鼠标左键点进去,一层一层追溯,结果懵逼了,发现里面涉及了很多以我目前实力看不懂的代码,怎么办?

    先不管三七二十一,因为根据之前看源码的经验,我发现如果一个方法的底层如果用了equals方法,那么它调用的是obj的equals方法。什么意思呢?就是说它其实调用的是被操作对象的方法,我们每一个Person4对象的equals方法,这样实现的目的应该是为了我们使用者可以方便地重写equals方法底层实现从而实现我们自己的个性化使用。
    我直接在person4里重写了equals方法如下:

    @Override
    	public boolean equals(Object obj) {
    		//先把obj强制转换成person4对象
    		Person4 p = (Person4) obj;
    		//改成根据各属性的值判断是否同一个对象
    		return p.name.equals(this.name) && p.age == p.age;
    	}
    

    再运行了下程序,发现并不起作用,重复元素还是存在。

    我再一咬牙,再把hashCode方法一并改写了:

    @Override
    	public int hashCode() {
    		return 10;
    	}
    

    我让hashCode方法都返回10,发现重复元素都没了。

    到了这里,不禁困惑,为什么这样就可以了呢?

    后来,经过查阅资料,观看视频得知,hashSet底层的add方法大概流程是这样的:先比较hashcode码,不相同则插入成功,如果相同,则用equals比较。

    再反观我们上面的程序,因为我让它hashcode都变成了10,所以他们最终都是通过equals比较的,equals被我重写,它就能够去掉重复的元素。

    但是,实际开发中这样效率是不高的,我们应该让它尽可能少调用方法,达到效率的提升,特别是操作的元素数量特别多的时候。

    所以,我们就应该让它在第一关:hashcode码判断的时候,就应该让不同的元素尽量返回不同的hashcode码,一次判断就结束。

    如果你使用的是eclipse,那么可以利用它自带的便捷功能:自动重写equals和hashcode方法,并且实现了我们上面提的要求(它为我们考虑好了算法)。按住shift+alt+s,点击generate hashCode( ) and equals( ),他会自动重写我们的两个方法。你想学习它的算法怎么实现的,可以看它生成的代码。

  • 相关阅读:
    04.
    24
    39
    46
    72.
    21.
    logout: not found”
    Username is not in the sudoers file. This incident will be reported
    激活函数
    排序算法
  • 原文地址:https://www.cnblogs.com/iisme/p/10480246.html
Copyright © 2020-2023  润新知