和Lsit接口同样,Set接口也是Collection接口的子接口,这两个接口的最大不一样是List接口中的子类集合内容容许重复,但java
是Set接口子类的集合容许重复,除此以外,Set接口没有对Collection接口进行扩充,因此Set接口中没有List接口中的get()方数据结构
法。你能够轻松的询问某个对象是否在某个Set中,因此查找是Set中最重要的操做。并且Set是根据对象的值来肯定归属性ide
的。 函数
如今看一下Set接口的类关系图,我再作下面的一系列介绍。this
Set接口有两个经常使用的实现子类:HashSet,TreeSet。
编码
HashSet:
spa
首先示例一个存放Integer对象的HashSet
3d
public class Main{ public static void main(String[] args){ Set<String> set = new HashSet<>(); set.add("Message C"); set.add("Message A"); set.add("Message B"); set.add("Message C"); set.add("Message D"); set.add("Message E"); set.add("Message B"); System.out.println(set); } }
根据结果咱们能够发现
code
1:虽然添加了重复的元素,可是结果中每一个元素只出现了一次
对象
2:HashSet存放数据彻底没有规律
出于速度的缘由,HashSet的元素存储使用了散列函数,而TreeSet的元素存储使用的是红黑树的数据结构。
HashSet重复元素判断
若是HashSet中存放的系统类对象,那么在进行重复元素判断的时候须要依靠ComParable接口来完成,例如Integer类就
实现了ComParable接口。可是,若是存放的是自定义类对象,因为其和ComParable接口没有关系,那么进行重复元素判断的
时候就须要覆写如下两个方法。
1:hash码:public native int hashCode();
2:对象比较: public boolean equals(Object obj);
对象比较的操做一共有两步:经过对象的hash码找到一个对象的信息,编码匹配以后在调用equals()进行内容的比较。
例子:覆写hashCode()与equals()方法消除重复元素
class Student implements Comparable<Student>{ private String name; private Integer age; public Student(String name, Integer age){ this.name = name; this.age = age; } @Override public String toString() { return "[name = "+this.name+" "+"age = "+this.age+"]"; } @Override public boolean equals(Object obj) { if(obj == null || getClass() != obj.getClass()){ return false; } if(obj == this){ return true; } if((obj instanceof Student)) { Student student = (Student) obj; return student.age.equals(this.age) && student.name.equals(this.name); } return false; } @Override public int hashCode() { return Objects.hash(name,age); } @Override public int compareTo(Student o) { if(this.age > o.age){ return 1; }else if(this.age < o.age){ return -1; }else { return this.name.compareTo(o.name); } } } public class Main{ public static void main(String[] args){ Set<Student> set1 = new HashSet<>(); set1.add(new Student("A",1)); set1.add(new Student("B",2)); set1.add(new Student("C",3)); set1.add(new Student("B",3)); set1.add(new Student("A",1)); System.out.println(set1);
由于使用hashSet,因此集合中元素是乱序的,可是在结果中已经去掉了重复的元素。
要注意的是,若是要去重,必定要同时覆写equals()和hashCode()两个方法,重复对象判断必须这两个方法同时返回相同
才能判断为相同。
TreeSet:
首先看TreeSet的使用方法,和hashSet的使用方法类似
public class Main{ public static void main(String[] args){ Set<String> set = new TreeSet<>(); set.add("Message C"); set.add("Message A"); set.add("Message B"); set.add("Message C"); set.add("Message D"); System.out.println(set); } }
咱们发现TreeSet相比于hashSet还实现了升序排序。
TreeSet排序:
若是进行的是自定义类对象的排序,那么对象所在的类就必须实现Comparable接口而且覆写compareTo()方法,而且类中
的全部属性都必须参加比较操做。
示例:使用TreeSet排列自定义类对象
class Person implements Comparable<Person> { private String name; private Integer age; public Person(String name, Integer age){ this.name = name; this.age = age; } @Override public String toString() { return "name = "+this.name+" age = "+this.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 class Main{ public static void main(String[] args){ Set<Person> set = new TreeSet<>(); set.add(new Person("A",1)); set.add(new Person("B",2)); set.add(new Person("C",3)); set.add(new Person("B",3)); set.add(new Person("A",1)); System.out.println(set); } }
由于在比较排序的时候类中全部属性都要参与比较,若是类中有不少属性的话,因此使用TreeSet存放自定义类对象过于麻
烦了,因此仍是推荐使用hashSet来存储自定义类对象。
去重的操做依靠Comparable接口来完成,因此咱们没必要像hashSet那样取覆写hashCode()方法和equals()方法。
关于Set接口的内容就现总结到这里,但愿能对你们有所帮助。