1、HashSet保持元素唯一性的方式
HashSet是如何保证元素的唯一性?是通过元素的两个方法,hashCode()和equals()来完成。如果元素的HashCode值相同,才会判断equals是否为true,如果元素的哈希值不同,不会调用equals。另外:若两个元素的值不同,地址值相同,过程是这样的:先比较地址值,发现相同,然后比较equals,发现值不同,则,在哈希表中,该地址值下回存入两个不同的对象,即一个地址两个对象,在打印时,可打印出这两个对象。
HashSet数据结构式哈希表,线程是非同步的。保证元素唯一性的原理,判断元素的hashCode是否相同,如果相同,还会继续判断元素的equals方法,是否为true
注意:对于判断元素是否存在以及删除等操作,都依赖于元素的hashcode和equals方法
class Demo
{
/*
public int hashCode()
{
return 60;//返回值3c, 十六进制形式
}
*/
}
class HashSetDemo
{
public static void sop(Object obj)
{
System.out.println(obj);
}
public static void main(String[] args)
{
Demo d = new Demo();
Demo d1 = new Demo();
sop(d);//因为重写了hashCode(),所以打印的d和d1的地址值是一样的
sop(d1);//这是因为,d.toString()时,调用hashCode(),返回d的哈希值
//但是我们重写后,返回的是3c,因此d 和d1打印地址值相同
HashSet hs = new HashSet();
hs.add("java01");
hs.add("java02");
hs.add("java03");
hs.add("java04");
hs.add("java03");
hs.add("java04");
sop(hs.add("java"));//add方法返回值为boolean的,此时打印true,能存
sop(hs.add("java"));//应为hs中已经存在java,不能继续存入,打印false
Iterator it = hs.iterator();
while(it.hasNext())//打印后只1234,因为HashSet中元素不重复
sop(it.next())
}
}
2、TreeSet的两种排序方式
排序的第一种方式:让元素自身具备比较性,元素实现compareable接口,覆盖compareTo()方法。这种方式也称为元素的自然顺序,或默认顺序。
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add("fd");
ts.add("cdf");
ts.add("Dd");
ts.add("b");
Iterator it = ts.iterator();
while(it.hasNext())
{
System.out.println(it.next());
//结果: Dd b cdf fd
//按首字母值排序,升序
}
}
}
/*
向TreeSet中存储自定义对象:重写compareTo方法,按我们自定义的方式返回值,先比较主要元素,若主要元素相同就比较次要元素。
*/
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
ts.add(new Student("zhangsan",19);
ts.add(new Student("lisi",30);
ts.add(new Student("wangwu",19);
ts.add(new Student("zhangsan",13);
Iterator it = ts.iterator();
while(it.hasNext())
{
System.out.println(it.next());
}
}
}
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 s = (Student)obj;
if(this.age>s.age)
return 1;
if(this.age==s.age)
return (this.name).compareTo(s.name);//String类本身就实现了Compareable接口,有compareTo方法
return -1;*/
//如果这样,那么元素是按存入的顺序排列的,存入元素时,会自动调用compareTo,返回1表示大于,返回0表示等于(此时不存入),返回-1表示小于。在这里全返回1表示后存入的对象比前一个对象大。
return 1;
}
public String getName()
{
return name;
}
public int getAge()
{
retrun age;
}
}
排序的第二种方式:当元素自身不具备比较性,或具备的比较性不是所需要的。这时需要让集合自身具备比较性。在集合一初始化时,就有了比较方式。定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数
当两种排序都存在时,以比较器为主
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 s = (Student)obj;
if(this.age>s.age)
return 1;
if(this.age==s.age)
return (this.name).compareTo(s.name);//String类本身就实现了Compareable接口,有compareTo方法
return -1;
}
public String getName()
{
return name;
}
public int getAge()
{
retrun age;
}
}
class TreeSetDemo
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet
(new MyCompare());
//表示使用指定比较器
ts.add(new Student("zhangsan",19);
ts.add(new Student("lisi",30);
ts.add(new Student("wangwu",19);
ts.add(new Student("zhangsan",13);
Iterator it = ts.iterator();
while(it.hasNext())
{
System.out.println(it.next());
//结果: Dd b cdf fd
//按首字母值排序,升序
}
}
}
定义一个类,实现Comparator接口,覆盖compare方法。
class MyCompare implements Comparator//自定义比较器
{
public int compare(Object c1,Object c2)
{
Student s1 = (Student)o1;
Student s2 = (Student)o2;
int num = s1.getName().compareTo(s2.getName());
if(num==0)//当name相同时,比较age
{
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge());
}
return num;
}
}
比较器调用过程:
就是让集合具备比较的功能,使用集合构造函数方法
创建TreeSet集合对象,此时:
TreeSet ts = new TreeSet(new MyCompare()); 表示使用自定义比较器
创建类实现接口Comparator,覆盖接口的compare方法
class MyCompare implements Comparator//自定义比较器
{
public int compare(Object c1,Object c2){
自定义比较的方式,最后的返回值return 正数或负数或0;一般就是1 -1 0
}
向TreeSet对象中添加元素,此时元素就自动的,按自定义的比较器在集合内排序存放}
compareTo调用过程理解:
让集合元素具备比较性
创建TreeSet集合对象,此时:
TreeSet ts = new TreeSet(); 表示使用compareTo()方法
创建类实现Comparable接口,覆盖compare方法。并且此类生成的对象,是准备向集合中添加的元素。
在覆盖后的compare方法中对该类的成员如name age等进行比较,返回值1 -1 或0
向集合中添加元素,集合就会自动调用compare方法,按覆盖后的compare方法进行排序存放