一.
往hashset中存储自定义对象。
既然存储的自定义对象,我们就要定义一个条件,什么条件呢?条件如截图中所示
先往里面存储自定义对象,通过迭代器将它们取出来(这是对之前所学的一个回顾)。在这里想问一句,迭代器将集合中的元素输出后,元素还存在么?
存入的是4,7,1,9但是输出的是4,7,9,1。这是无序的,无序的原因就是,体系采用算法得出存储的位置。
现在对程序做修改,添加了两次lisi7
输出的结果中居然出现了两次lisi7,不是说hashset保证唯一么。(说明对象和字符串之类的数据还不一样)
这里面有两个问题,分析一下,第一个hashset集合在存元素的时候,它依赖的是元素的hashcode方法和equals方法,
如果上面的截图看懂了,你就知道了,我在往里面存ab的时候,我先要调用这个算法,着算法就是hashcode,只不过在这里的截图中我们写成了funciton,
我们着person有哈希值么?这个person类继承自object,它是有哈希值的,而这个哈希值调用的是系统的哈希值,因为它用的是object中的hashcode方法,
它是本地的,有native,走的是系统的,它在帮我们计算。
有没有equals方法?有的,用的也是父类的,是在判断地址(equals方法具体判断的是什么?)不同对象有不同地址,equals方法判断地址不同,代表着对象不相符。
所以你往里面存储了五个对象,每个对象都有自己的位置,它们的equals都不相同。所以hashset认为,这是五个不同的对象。
第二个问题是:你说同姓名同年龄,这个条件,hashset容器知道么?你定义了条件,你有把条件告诉它么?没有。
那么,我们怎么告诉它?我是不是应该创建person对象自己的hashcode方法和equals方法。我们应该依赖人特有的一些内容来算,人这个对象的位置,
windows算的时候,按照它的算的,我想说按照我制定的条件算,怎么办?就是重新赋写这两个方法。保留功能,建立自己的内容。
注释:前面讨论的时候是以字符串来说的,现在以对象来讨论,但是对象在存储时碰到了问题,我们需要对其进行修改。
怎么覆盖?out+shift+s,看下面的截图,显示的是调用父类的方法,现在我们进行修改。
现在考虑哈希值怎么写?原先是按照int算的,有人提出年龄就是int,以年龄为哈希值。写成0或着100都没问题,但是写成年龄更好,因为每个年龄不一样,
要是返回值的话,随便返回都可以,如果返回100,意味着这些对象都存在一位上,内容不相同可以顺延。写成age,可以避免或者减少了哈希冲突。
一减少哈希冲突,就避免了调用equals方法。如果是用age的话,比如说"lisi4, 28", "lisi7, 28",这两个对象还要进行equals方法判断,人所具备的因素有两个,一个是姓名,一个是年龄。可以统一一起来算哈希值,更能保证唯一。
如果这么弄的话,name是字符串,返回值类型不对。但是字符串有hashcode,姓名有自己的哈希值,再加上年龄,就是这个人特有的哈希值。这样就唯一了,省得判断equals了。
如果哈希值相同的话,还要接着判断内容,比如都是lisi7,27。equals返回时是false,就挂了。哈希值相同,equals不同,它们还是不同对象(不是说对象本身不是不同对象,而是系统在给它存储的时候,存成了不同对象)。所以,equals也要依赖于哈希值条件,来判断equals相同。
hashcode是判断人的哈希值是否相同,而equals是判断人的内容是否相同。
内第一个equals判断的是对象间内容是否相同(对象的equals方法),第二个是字符的equals方法。
这里的程序是分开来的,一个只负责存储和输出,另一个对集合的数据结构进行优化。对person类的内容进行调整优化后,当存储两个相同的自定义对象时,结果和之前不一样了。
再次修改程序,只存储一个自定义对象,
在算hashcode时,打印一次this。
注释:在集合中存储自定义对象时,会存在一个问题,就是两个相同的自定义对象能够存储和输出,如果不自定义hashcode和equals方法的话,只是借用系统的hashcode和equals方法。现在,我们对自定义的对象的hashcode和equals方法进行重写,使得相同的自定义对象不能输出。不同的元素是可以存储的,可以存储在一个格子上(顺延),也可以存在不同格子上。
插曲,一般在hashcode中会多乘一个38,这个数字是随机的,为了保证哈希值唯一。
如果输入相同相同的对象,后面还要进行判断删除。因此直接在开头就进行判断。同时,还要保证是相同的类进行对比。