Set集合中元素的保存问题(hashSet和treeSet中不能存放相同元素)

来源:互联网 发布:网络推广 photoshop 编辑:程序博客网 时间:2024/06/05 20:31

1.对于hashSet集合,一般需要覆写类中的hashCode()方法和equals()方法。

比如下面代码

class  testhash{public static void main(String[] args) {compare();}public static void compare(){HashSet hs=new HashSet();Student stu1=new Student("zhangsan",21);Student stu2=new Student("liming",18);Student stu3=new Student("liming",18);hs.add(stu1);hs.add(stu2);hs.add(stu3);Iterator it=hs.iterator();while (it.hasNext()){Student stu=(Student)it.next();System.out.println("name:"+stu.getName()+"---age:"+stu.getAge());}}
打印结果为:

name:liming---age:18
name:liming---age:18
name:zhangsan---age:21

由此可以看见hashSet中保存了两个内容相同的元素。为什么保存成功了呢?主要因为第一个方法hashCode()方法返回的是类的引用,引用当然是不相等的,所以系统就认为两者不等,所以就可以保存。

如果上面还不明白看下面代码:

public static void compare(){HashSet hs=new HashSet();Student stu1=new Student("zhangsan",21);Student stu2=new Student("liming",18);Student stu3=new Student("liming",18);String str1=new String("abc"); str1="java";String str2="java";hs.add(stu1);hs.add(stu2);hs.add(stu3);hs.add(str1);hs.add(str2);Iterator it=hs.iterator();while (it.hasNext()){//Student stu=(Student)it.next();//System.out.println("name:"+stu.getName()+"---age:"+stu.getAge());System.out.println(it.next());}}

打印结果为:

Student@6af62373
Student@459189e1
Student@3ce53108
java

说明str1和str2只保存了一个那是因为String类中已经覆写了hashCode() 和equals()方法,hashCode和equals都是相等的

所以若要使hashSet中存放不同的元素则必须对Student中的这两个方法进行覆写。

代码如下

class Student {private String name;private int age;Student(String name,int age){this.name=name;this.age=age;}//重写hashCodepublic int hashCode(){return age*name.hashCode();}public boolean equals(Object obj){if (!(obj instanceof Student))return false;Student stu=(Student)obj;System.out.println(this.name+"----"+stu.name);boolean m=this.name.equals(stu.name)&&this.age==stu.age;return m;}public String getName(){return name;}public int getAge(){return age;}public void setName(String name){this.name=name;}public void setAge(int age){this.age=age;}}class  testhash{public static void main(String[] args) {compare();//test1();}public static void compare(){HashSet hs=new HashSet();Student stu1=new Student("zhangsan",21);Student stu2=new Student("liming",18);Student stu3=new Student("liming",18);hs.add(stu1);hs.add(stu2);hs.add(stu3);Iterator it=hs.iterator();while (it.hasNext()){Student stu=(Student)it.next();System.out.println("name:"+stu.getName()+"---age:"+stu.getAge());}}public static void test1(){String str1=new String("abc");String str2="abc";String s="hello";s="java";String s1="java";System.out.println("-----");System.out.println(s.equals(s1));System.out.println(str1.equals(str2));  //二者的hashCode 是相等的System.out.println(str1.hashCode()+"--"+str2.hashCode());} }
如此的话stu2和stu3就只保存了一个。

也就是说对于hashSet保证元素唯一性的方法是通过覆盖元素的两个方法hashCode()和equals()方法来判断元素是否相等,如果hashCode()的值相等才会调用equals()方法,否则不会调用equals()方法,这样在一定程度上也提高了工作的效率,不用每次都调用equals()方法。
2.对于treeSet集合保证元素唯一性的方法主要有两个:

(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 stu=(Student)obj;//最基本写法if (this.age>stu.age){return 1;}if (this.age==stu.age){return this.name.compareTo(stu.name);}return -1;}public String getName(){return name;}public int getAge(){return age;}public void setName(String name){this.name=name;}public void setAge(int age){this.age=age;}}class testhash{public static void main(String[] args){test1();}public static void test1(){TreeSet ts=new TreeSet();Student stu1=new Student("zhangsan",21);Student stu3=new Student("liming",18);Student stu4=new Student("wangwu",27);Student stu2=new Student("liming",18);ts.add(stu1);ts.add(stu2);ts.add(stu3);ts.add(stu4);Iterator it=ts.iterator();while (it.hasNext()){Student stu=(Student)it.next();System.out.println("name:"+stu.getName()+"---age:"+stu.getAge());}}}

打印结果为:

name:liming---age:18
name:zhangsan---age:21
name:wangwu---age:27

需要注意的是对于treeSet如果实现comparable接口编译可以通过但运行会报错。如果覆盖compareTo()方法时直接在方法体内写return 0;则此时TreeSet只能保存第一个元素,其他的都存不进去,而如果return 1,则会把所有元素存进去,不按年龄顺序。这种方式也称为元素的自然排序,或者叫默认排序。

(2).定义一个类实现Comparator接口,覆盖compare()方法

代码如下:

class testhash{public static void main(String[] args){test1();}public static void test1(){TreeSet ts=new TreeSet(new myCompare());Student stu1=new Student("zhangsan",21);Student stu3=new Student("liming",18);Student stu4=new Student("wangwu",27);Student stu2=new Student("liming",18);ts.add(stu1);ts.add(stu2);ts.add(stu3);ts.add(stu4);Iterator it=ts.iterator();while (it.hasNext()){Student stu=(Student)it.next();System.out.println("name:"+stu.getName()+"---age:"+stu.getAge());}}}//定义一个类实现Comparator接口,覆盖compare()方法class myCompare implements Comparator{public int compare(Object obj1,Object obj2){Student stu1=(Student)obj1;Student stu2=(Student)obj2;int num=stu1.getName().compareTo(stu2.getName());if (num==0){return new Integer(stu1.getAge()).compareTo(new Integer(stu2.getAge()));}return num;}}

如果两种排序都存在时,以比较器为准,如上如果Student中继承自comparable接口且尤其实现方法时,以下面定义的myCompare比较器为准。


0 0
原创粉丝点击