Set集合最大的特点就是不允许保存重复元素,其也是Collection子接口。
Set接口简介
Set集合定义如下:
public interface Set<E> extends Collection<E>
Set集合并不像List集合那样扩充了许多的新方法,所以无法使用List集合中提供的get方法,也就是无法实现指定索引数据的获取。
package demo;
import java.util.Set;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
//进行Set集合数据的保存,并且设置有重复的内容
Set<String> all = Set.of("hello","world","heheda","Hello","hello");
all.forEach(System.out::print);
}
}
因为有重复元素“hello”,此段程序或直接报错:Exception in thread "main" java.lang.IllegalArgumentException: duplicate element: hello
;
当使用of()这个新方法的时候如果发现集合之中存在有重复元素则会直接抛出异常。这与传统的Set集合不保存重复元素的特点相一致,只不过自己抛出了异常。
Set集合的常规使用形式一定是依靠子类进行实例化的,所以Set接口之中有两个常用子类:HashSet、TreeSet。
HashSet子类
HashSet子类是Set接口里面使用最多的一个子类,其最大的特点就是保存的数据是无序的,而HashSet子类的继承关系如下:
public class HashSet<E> extends AbstractSet<E> implements Set<E>,Cloneable,Serializable
。
这种继承的形式合ArrayList相似的。
【范例】HashSet子类
package demo;
import java.util.HashSet;
import java.util.Set;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
//进行Set集合数据的保存,并且设置有重复的内容
Set<String> all = new HashSet<String>();
all.add("hello");
all.add("Hello");
all.add("world");
all.add("BILIBILI");
all.add("hello");
all.forEach(System.out::println);
}
}
HashSet子类的特点:不允许保存重复元素(Set接口定义),HashSet之中保存的顺序是无需的。
TreeSet子类
Set接口的另外一个子类就是TreeSet,与HashSet最大的区别在于TreeSet集合里面保存的数据是有序的。TreeSet定义如下:
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, Serializable
。
【范例】使用TreeSet子类
package demo;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
//进行Set集合数据的保存,并且设置有重复的内容
Set<String> all = new TreeSet<String>();
all.add("hello");
all.add("Hello");
all.add("world");
all.add("BILIBILI");
all.add("hello");
all.forEach(System.out::println);
}
}
当利用TreeSet保存的数据的时候所有的数据都将按照数据的升序进行自动排序处理。
TreeSet排序说明
TreeSet子类之中保存的数据是允许排序的,但是这个类必须要实现Comparable接口,因为只有实现了此接口,才能够确认出对象的大小关系。
TreeSet本质是利用TreeMap子类实现的集合数据的存储,而TreeMap就需要根据Comparable来确定大小关系。
【范例】实现自定义类排序
package demo;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;
public class JavaAPIDemo {
public static void main(String[] args) throws Exception {
//进行Set集合数据的保存,并且设置有重复的内容
Set<Person> all = new TreeSet<Person>();
all.add(new Person("李四",20));
all.add(new Person("李四",21));
all.add(new Person("王五",22));
all.add(new Person("张三",19));
all.add(new Person("张三",20));
all.forEach(System.out::println);
}
}
class Person implements Comparable<Person>{
private String name;
private int age;
public Person(String name, int age) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return "姓名:" + this.name +"、年龄:" + this.age;
}
@Override
public int compareTo(Person per) {
if(this.age<per.age) {
return -1;
}else if(this.age == per.age) {
return this.name.compareTo(name);
}else {
return 1;
}
}
}
姓名:张三、年龄:19
姓名:李四、年龄:20
姓名:李四、年龄:21
姓名:王五、年龄:22
此代码运行结果有问题,20岁的张三没有了,暂未搞明白原因。当换成HashSet时就能全部存在。
在使用自定义类对象比较的时候一定要将该类之中的所有属性都一次进行大小关系的匹配,否则如果某一个属性或某几个属性相同的时候,它也会认为是重复数据。所以TreeSet是利用了Comparable来确认重复数据的。
由于TreeSet在操作过程之中需要将类中的所有属性进行比对,这样的实现难度太高,所以实际之中应该首选HashSet进行存储。
参考地址:https://edu.aliyun.com/lesson_1012_9076?spm=5176.10731542.0.0.be19d290nr01qR#_9076