一.
往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,这个数字是随机的,为了保证哈希值唯一。
如果输入相同相同的对象,后面还要进行判断删除。因此直接在开头就进行判断。同时,还要保证是相同的类进行对比。
package hassetdemo.demo;
import java.util.HashSet;
import java.util.Iterator;
import javax.print.attribute.standard.MediaSize.Other;
import arraylist.test.Person;
public class HasSetDemo {
public static void main(String[] args) {
HashSet hs = new HashSet();
show1(hs);
}
private static void show1(HashSet hs) {
hs.add(new Person("lisi5",24));
hs.add(new Person("lisi6",25));
hs.add(new Person("lisi7",26));
hs.add(new Person("lisi7",26));
hs.add(new Person("lisi3",6));
hs.add(new Person("lisi1",2));
Iterator it = hs.iterator();
while (it.hasNext()) {
Person p = (Person) it.next();
System.out.println(p.getName()+":"+p.getAge());
}
}
//输出结果
// lisi6:25
// lisi5:24
// lisi7:26
// lisi3:6
// lisi1:2
}
package arraylist.test;
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
// super();
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
// System.out.println(this.getClass());
// System.out.println(obj.getClass());
if (this == obj)
return true;
if(!(obj instanceof Person))
throw new ClassCastException("类型错误");
Person p = (Person) obj;
return this.name.equals(p.name)&&this.age==p.age;
}
@Override
public int hashCode() {
//字符串有自己的HashCode
return name.hashCode()+age*39;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}