Java Set集合 1 Set集合 2 常用方法 3 实现类 4 HashSet和TreeSet区别

一个不包含重复元素的 collection。更确切地讲,set 不包含满足 e1.equals(e2) 的元素对 e1 和 e2,并且最多包含一个 null 元素。正如其名称所暗示的,此接口模仿了数学上的 set 抽象。

public interface Set<E> extends Collection<E>

特点:无序、无下标、元素不可重复
方法:全部继承自Collection中的方法

2 常用方法

Java Set集合
1 Set集合
2 常用方法
3 实现类
4 HashSet和TreeSet区别

3 实现类

3.1 HashSet[重点]

  • 基于HashCode、equals实现元素不重复
  • 当存入元素的哈希码相同时,会调用equals进行确认,如结果为true,则拒绝后者存入
  • 存入的元素要重写hashCode和equals方法

基本用法

/**
 * HashSet的使用
 *      存储结构:哈希表(数组+链表+红黑树)
 */
public class Set1 {
    public static void main(String[] args) {

        //创建集合
        Set<String> stringSet = new HashSet<>();
        //添加元素
        stringSet.add("小米");
        stringSet.add("华为");
        stringSet.add("苹果");
        stringSet.add("苹果");//只能保存一个相同的元素
        stringSet.add(null);
        stringSet.add(null);//可以存放一个null
        System.out.println(stringSet);//打印无序
        //删除
        stringSet.remove("苹果");
        System.out.println(stringSet);

        /**
         * 遍历
         */
        System.out.println("****增强for****");

        for (String s : stringSet) {
            System.out.println(s);
        }
        System.out.println("****迭代器****");
        Iterator<String> stringIterator = stringSet.iterator();
        while (stringIterator.hasNext()){
            System.out.println(stringIterator.next());
        }

        //判断
        boolean containsXiaoMi = stringSet.contains("小米");
        System.out.println(containsXiaoMi);
        System.out.println("集合大小:"+stringSet.size());

    }
}

运行结果

[null, 苹果, 华为, 小米]
[null, 华为, 小米]
****增强for****
null
华为
小米
****迭代器****
null
华为
小米
true
集合大小:3

存放对象

public class Person {

    private String name;
    private int age;

   
    //getter、setter、构造器、toString

    /**
     * 重写hashCode和equals方法
     */
    @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 &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

}


/**
 * HashSet的使用
 *      存储结构:哈希表(数组+链表+红黑树)
 *      存储过程:
 *          1、根据hashCode计算保存的位置,如果此位置为空,则直接保存,如果不为空执行第二步
 *          2、再执行equals方法,如果equals方法为true,则认为时重复,否则,形成链表
 */
public class Set2 {
    public static void main(String[] args) {
        HashSet<Person> personHashSet = new HashSet<>();
        Person p1 = new Person("婉儿",18);
        Person p2 = new Person("公孙离",18);
        Person p3 = new Person("妲己",18);
        personHashSet.add(p1);
        personHashSet.add(p2);
        personHashSet.add(p3);
        personHashSet.add(null);

        /**
         * 因为Person重写了hashCode和equals方法,不能再重复添加了
         *
         */
        personHashSet.add(new Person("妲己",18));
        System.out.println(personHashSet);
    }
}

运行结果:

[null, Person{name='婉儿', age=18}, Person{name='妲己', age=18}, Person{name='公孙离', age=18}]

3.2 TreeSet

  • 基于排列顺序实现元素不重复
  • 实现了SortedSet接口,对集合元素自动排序
  • 元素对象的类型必须实现Comparable接口,指定排序规则
  • 通过CompareTo方法确定是否为重复元素

基本用法


/**
 * TreeSet的使用:
 *      存储结构:红黑树
 *      要求:元素必须实现Comparable接口,compareTo()方法返回值为0,认为是重复元素
 */
public class Set3 {
    public static void main(String[] args) {
        //创建集合 String类已经实现了Comparable接口,可以直接添加
        Set<String> stringSet = new TreeSet<>();
        stringSet.add("hello");
        stringSet.add("abc");
        stringSet.add("xyz");
        stringSet.add("xyz");//重复元素不能添加
        //stringSet.add(null); //发现不能存放null
        System.out.println(stringSet);//发现集合已经排序了

        //Person类需要实现Comparable接口,实现compareTo方法
        Set<Person> personSet = new TreeSet<>();
        Person p1 = new Person("x婉儿",18);
        Person p2 = new Person("a公孙离",18);
        Person p3 = new Person("d妲己",18);
        Person p4 = new Person("d妲己",16);
        personSet.add(p1);
        personSet.add(p2);
        personSet.add(p3);
        personSet.add(p4);
        System.out.println(personSet);

        //查询某个元素是否存在
        boolean b = personSet.contains(new Person("d妲己", 16));
        System.out.println(b);
        //集合大小
        System.out.println("大小:"+personSet.size());
        //删除某个元素 comparedTo方法的返回值相同就认为元素存在,就可以删除
        System.out.println(personSet.remove(new Person("d妲己", 16)));
        //清空集合
        personSet.clear();

        //遍历
        //迭代器
        //增强for

    }
}
public class Person implements Comparable<Person>{

    private String name;
    private int age;

    //getter、setter、构造器、toString

    /**
     * 定义排序规则:名字,年龄
     */
    @Override
    public int compareTo(Person o) {
        int byName = this.name.compareTo(o.name);
        int byAge = this.age - o.age;
        return byName==0 ? byAge : byName;
    }

}

运行结果

[abc, hello, xyz]
[Person{name='a公孙离', age=18}, Person{name='d妲己', age=16}, Person{name='d妲己', age=18}, Person{name='x婉儿', age=18}]
true
大小:4
true

也可以通过TreeSet的构造方法传入Comparator指定比较规则,这样元素就可以不用实现Comparable接口了

public class Set3 {
    public static void main(String[] args) {

        //通过TreeSet的构造方法传入Comparator指定比较规则
        
        //使用匿名内部类
        Set<Person> personSet2 = new TreeSet<>(new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                int byName = p1.getName().compareTo(p2.getName());
                int byAge = p1.getAge()- p2.getAge();
                return byName==0 ? byAge:byName;
            }
        });
            
        //使用Lambda表达式
        Set<Person> personSet = new TreeSet<>((p1,p2)->{
            int byName = p1.getName().compareTo(p2.getName());
            int byAge = p1.getAge()- p2.getAge();
            return byName==0 ? byAge:byName;
        });

        Person p1 = new Person("x婉儿",18);
        Person p2 = new Person("a公孙离",18);
        Person p3 = new Person("d妲己",18);
        Person p4 = new Person("d妲己",16);
        personSet.add(p1);
        personSet.add(p2);
        personSet.add(p3);
        personSet.add(p4);
        System.out.println(personSet);

    }
}

TreeSet练习 根据字符串长度排序

4 HashSet和TreeSet区别

HashSet
不能保证元素的排列顺序,顺序有可能发生变化
集合元素可以是null,但只能放入一个null
HashSet底层是采用HashMap实现的
HashSet底层是哈希表实现的

TreeSet
Treeset中的数据是排好序的,不允许放入null值。
TreeSet是通过TreeMap实现的,只不过Set用的只是Map的key。
TreeSet的底层实现是采用二叉树(红-黑树)的数据结构