Set接口与上文所讲的List接口的区别是:
不能加入重复的元素;
接口的实例无法像List接口那样可以进行双向输出;
List接口对Collection接口进行了扩充,Set没有对Collection进行扩充,只是比Collection要求更严格了(不能加重复元素)。
set接口下面有两个常用的子类:HashSet、TreeSet和一个子接口SortedSet,下面对这几个一一介绍。
HashSet、TreeSet:Set--->无重复,Hash---->无序,Tree---->有序
本节主要介绍TreeSet的排序,去重;HashSet的去重。
1、散列存放:HashSet
hashset的实现依赖hash函数,哈希值。主要特点,里面不能存放重复的元素,采取散列的存储方式,所以没有顺序。
2、有序的存放:TreeSet
程序在向集合插入数据的时候是无序的,输出是有序的。
需要说明以下的例子并没有证明HashSet的无序性,以后在深入研究一下。现在先看一下他们的使用
public class HashSetDemo01 {
public static void main(String[] args) {
Set<String> allSet = new HashSet<String>();
allSet.add("A");
allSet.add("B");
allSet.add("D");
allSet.add("D");//重复元素不能加入
allSet.add("C");
allSet.add("E");
System.out.println(allSet);
Set<String> allSet1 = new TreeSet<String>();
allSet1.add("E");
allSet1.add("C");
allSet1.add("B");
allSet1.add("C");//重复元素不能加入
allSet1.add("A");
allSet1.add("D");
System.out.println(allSet1);
}
}
输出结果:
[A, B, C, D, E]
[A, B, C, D, E]
怎样实现TreeSet的排序呢?TreeSet中元素是有序存放的,所以对于每一个对象必须指定好排序规则,而且TreeSet中的每个对象所在的类必须实现Comparable接口才可以正常使用。
如果你想对自己写的类排序,你就把自己写的这个类实现Comparable接口,然后重写comparaTo方法来规定这个类的对象排序的顺序。
在这个方法中,如果返回-1,则当前对象排前面;返回1,就排后面 ;0,就相等。
public class TreeSetDemo01 {
/**
* TreeSet排序
* @param args
*/
public static void main(String[] args) {
Set<Person> allSet = new TreeSet<Person>();
allSet.add(new Person("张三", 20));
allSet.add(new Person("李四", 22));
allSet.add(new Person("王五", 24));
allSet.add(new Person("王五", 24));
allSet.add(new Person("赵六", 28));
allSet.add(new Person("赵七", 28));
System.out.println(allSet);//如果不重写toString的话则输出的是地址
}
}
class Person implements Comparable<Person>{//定义一个Person类,实现比较器
private String name;
private int age;
// 通过构造方法为属性赋值
public Person(String name, int age){
this.name = name;
this.age = age;
}
// 为了输入方便,重写toString方法,如果重写toString的话则输出的是地址
public String toString(){
return "姓名:"+this.name+";年龄:"+this.age;
}
// 排序规则
@Override
public int compareTo(Person person) {
if(this.age > person.age){
return 1;//this.age排后面
}else if(this.age < person.age){
return -1;//this.age排前面
}else{
return this.name.compareTo(person.name);//增加字符串比较,年龄相等的话区分姓名
} //如果姓名年龄都相等的话,为重复元素,不再排出来
}
}
输出结果:
[姓名:张三;年龄:20, 姓名:李四;年龄:22, 姓名:王五;年龄:24, 姓名:赵七;年龄:28, 姓名:赵六;年龄:28]
以上例子实现了TreeSet“去重复”、“排序”的功能,都是通过Comparable接口完成的。
然而对于HashSet此方法不能“去重”、”排序“,HashSet是无法排序的,他本身存储是无序的,排序无用,同时Comparable接口中实现的”去重“方法也不能实现了。
那么,如何针对HashSet进行去重复元素呢?
4、HashSet(后面会讲到HashMap)利用equals、HashCode去重复元素
equals--->判断对象是否相等;
HashCode--->判断对象的编码是否相等
class Person2 {
private String name;
private int age;
public Person2(String name, int age){
this.name = name;
this.age = age;
}
public boolean equals(Object obj){
if(this == obj){
return true;//地址相同是同一个对象
}
if(!(obj instanceof Person2)){
return false;//传递过来的不是本类对象,不是同一个对象
}
Person2 p = (Person2) obj;//向下转型
if(this.name.equals(p.name)&&this.age == p.age){//全部属性相等,是同一个对象
return true;
}else{
return false;
}
}
public int hashCode(){//重写HashCode
return this.name.hashCode()*this.age;
}
public String toString(){
return "姓名:"+this.name+";年龄:"+this.age;
}
}
public class TreeSetDemo01 {
/**
* HashSet去重
* @param args
*/
public static void main(String[] args) {
Set<Person2> allSet1 = new HashSet<Person2>();
allSet1.add(new Person2("张三", 20));
allSet1.add(new Person2("李四", 22));
allSet1.add(new Person2("王五", 24));
allSet1.add(new Person2("王五", 24));
allSet1.add(new Person2("赵六", 28));
allSet1.add(new Person2("赵七", 28));
System.out.println(allSet1);
}
}
输出结果:
[姓名:赵七;年龄:28, 姓名:李四;年龄:22, 姓名:张三;年龄:20, 姓名:赵六;年龄:28, 姓名:王五;年龄:24]
以上就是HashSet去重复元素的实现。
下文介绍Map接口。