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比较器为准。