您的位置:首页 > 其它

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

2014-11-15 12:28 387 查看
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;
}
//重写hashCode
public 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比较器为准。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐