一篇文章带你搞懂 Java 中的 Set 接口

一、Set 接口的定义

Set 接口也是 Collection 接口的子接口,但是与 Collection 或者 List 接口不同,Set接口不能加入重复的元素。

public interface Set<E> extends Collection<E>

Set 接口主要方法与 Collection 接口一致,并没有对其进行扩充,只是比 Collection 接口的要求更加严格,不能增加重复的元素

Set 接口的实例无法像 List 接口进行双向输出,因为此接口没有提供像 List 接口定义的 get(int index)方法

二、Set 接口的常用子类

1. 散列的存放:HashSet

HashSet 是 Set 接口的一个子类,主要特点是:里面不能存放重复元素,而且采用散列的存储方式,所以没有顺序

import java.util.HashSet;
import java.util.Set;

public class Test{
          
   
    public static void main(String[] args) {
          
   
        Set<String> allSet = new HashSet<String >();
        allSet.add("A");
        allSet.add("B");
        allSet.add("B");//重复元素,不能加入
        allSet.add("C");
        System.out.println(allSet);//输出集合对象,调用 toString()
    }
}

结果可以看出,对于重复元素只会增加一次,而且程序运行时向集合中加入元素的顺序并不是集合中的保存顺序,HashSet 类中的元素时无序排列的

2. 有序的存放:TreeSet

如果想对输入的数据有序排列,需要使用 TreeSet 子类。TreeSet 类的定义:

public class TreeSet<E> extends AbstractSet<E> implements SortedSet<E>,
Cloneable,Seriallizable

TreeSet 类也是继承了 AbstractSet 类,此类的定义如下:

public abstract class AbstractSet<E> extends AbstractCollection<E> 
implements Set<E>
import java.util.Set;
import java.util.TreeSet;

public class Test{
          
   
    public static void main(String[] args) {
          
   
        Set<String> allSet = new TreeSet<String >();
        allSet.add("D");
        allSet.add("B");
        allSet.add("B");//重复元素,不能加入
        allSet.add("C");
        allSet.add("D");//重复元素,不能加入
        allSet.add("A");
        System.out.println(allSet);//输出集合对象,调用 toString()
    }
}

向集合中插入数据时是没有顺序的,但是输出之后数据是有序的,所以 TreeSet 是可以排序的子类。

3. 自定义类排序

通过覆写 equals() 方法和 hashCode() 方法去掉集合中的重复

import java.util.HashSet;
import java.util.Set;

class Person{
          
   
    private String name;
    private int age;
    public Person(String name,int age){
          
   
        this.name = name;
        this.age = age;
    }
    public boolean equals(Object obj){
          
   //覆写 equals() 方法
        if (this == obj){
          
   //地址相同
            return true;//是同一个对象
        }
        if (!(obj instanceof Person)){
          
   //传递进来的不是本类的对象
            return false;//不是同一个对象
        }
        Person p = (Person)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(){
          
   //覆写 toString() 方法
        return "姓名:" + this.name + ";年龄:" + this.age;
    }
}
public class Test{
          
   
    public static void main(String[] args) {
          
   
        Set<Person> allSet = new HashSet<Person>();//实例化 Set 接口对象
        allSet.add(new Person("张三",30));//加入元素
        allSet.add(new Person("李四",31));//加入元素
        allSet.add(new Person("王五",32));//加入元素
        allSet.add(new Person("王五",32));//重复元素,不能加入元素
        allSet.add(new Person("赵六",33));
        allSet.add(new Person("孙七",33));//年龄重复
        System.out.println(allSet);
    }
}
经验分享 程序员 微信小程序 职场和发展