Set也是Collection的子接口,主要特点是保存的数据不允许出现重复。但Set子接口并不像List子接口那样,针对Collection接口进行扩展,而是完整按照Collection接口标准实现了继承,所以没有get方法。
Set子接口有两个常用子类:TreeSet(有序)、HashSet(无序)。
【举例】:观察HashSet子类:HashSet最大特点是不允许保存重复元素,且无序排列。
Set<String> all = new HashSet<String>();
all.add("Hello");
all.add("World");
all.add("good");
all.add("dog");
all.add("cat");
all.add("Hello"); //重复元素不保存
System.out.println(all);
【举例】:观察TreeSet子类:数据不允许重复,根据升序排列
Set<String> all = new TreeSet<String>();
all.add("Hello");
all.add("World");
all.add("good");
all.add("dog");
all.add("cat");
all.add("Hello");
System.out.println(all);
可以使用自定义类作为保存数进行排序,但是一定要实现Comparable接口,以作为排序的依据。而在实现Comparable接口时,需要将所有属性参与到比较中,具体查看下面的compareTo方法,若只写return this.age-o.age,则运行输出,发现只有张三和赵五,年龄相同李四没有了。
Set<Person> all = new TreeSet<Person>();
all.add(new Person("张三",10));
all.add(new Person("赵五",12));
all.add(new Person("李四",10));
all.add(new Person("赵五",12));
System.out.println(all);
class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}' ;
}
@Override
public int compareTo(Person o) {
if(this.age > o.age){
return 1;
}else if(this.age < o.age){
return -1;
}else{
return this.name.compareTo(o.name);
}
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
只要Java中牵扯到一组对象的排序操作,永远要使用Comparable接口完成,上例中可以看出,使用TreeSet进行排序,需要将所有属性参与到比较中,比较麻烦,所以一般很少用TreeSet进行比较操作,多用HashSet。
Comparable只是适合于TreeXX类型的集合消除重复元素,而真正意义的重复判断不是利用Comparable接口完成,而是利用Object类的两个方法完成:
Set<Person> all = new HashSet<>();
all.add(new Person("张三",10));
all.add(new Person("赵五",12));
all.add(new Person("李四",10));
all.add(new Person("赵五",12));
System.out.println(all);
class Person{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}' ;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
name.equals(person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
1)Set接口重复数据消除依靠的是子类实现,HashSet基于hashCode()、equals(),TreeSet基于Comparable接口。
2)开发中很少用TreeSet,基本用的是HashSet。