【set】集合总结

该文章已生成可运行项目,

一、Set

Set集合是Collection的子接口,代表一种集合,此种集合是元素不重复.

有两个常用实现类

  • HashSet 是元素不重复,无序,主要是指遍历顺序和插入顺序不一致

  • TreeSet 是元素不重复,排序

  • LinkedHashSet不常用

二、HashSet

1.1 介绍

  • HashSet是Set的实现类

  • 底层是由哈希表实现,其实实际是HashMap实现

  • 允许重复,,无序,主要是指遍历顺序和插入顺序不一致

  • 不保证线程安全,即不同步

  • 方法与父接口Set,Collection中基本一致,就是最基本的集合方法,没有关于下标操作

1.2 演示API

练习常用方法

  • 构造方法

  • 添加,删除,清空,大小,迭代,toArray


掌握: 基本方法使用,演示出去重,遍历顺序问题!!!

public static void main(String[] args) {
        HashSet<Integer> set = new HashSet<>();
        set.add(11);
        set.add(22);
        set.add(33);
        set.add(44);
        set.add(55);
        System.out.println(set.contains(11));   //判断是否包含某个元素
        System.out.println(set.isEmpty());      //判断是否为空
        set.remove(11);                      //移除某个元素
        System.out.println(set.size());         //返回set的大小
        Iterator<Integer> iterator = set.iterator();    //使用迭代器迭代set中的元素
        while (iterator.hasNext()){
            System.out.print(iterator.next()+" ");
        }
        for (Integer i : set) {                 //使用foreach遍历set中的元素,语法糖,等同与迭代器
            System.out.print(i+" ");
        }
    }

1.3 底层原理

  • HashSet底层是哈希表

  • 更直接的是HashSet底层是HashMap

    • 创建HashSet时,其实创建了HashMap

      image-20240605143913477

    • 向set集合add添加元素,其实放在HashMap集合中

      image-20240605144018121

HashSet去重的原理?

  • 向set中存储运算时,调用元素本身的hashCode方法,获得地址值

  • 如果这个地址值在set集合中如果没有相同,就将该元素存储到集合

  • 如果这个地址值在set集合中有相同的,此时调用元素的equals来做判断

    • 如果equals判断为true,属性全部相同,则不存储该元素,即去重

    • 如果equals判断false,属性值有不相同,则存储该元素


简单说就是:

  • 存储的元素地址值不一样,直接存储

  • 地址值一样,再比较equals

    • eqauls判断不等,直接存储

    • equals判断相等,不存

三、LinkedHashSet

        排序且去重

public static void main(String[] args) {
            LinkedHashSet<Integer> lhs = new LinkedHashSet<>();
            lhs.add(3);
            lhs.add(3);
            lhs.add(1);
            lhs.add(5);
            lhs.add(5);
            lhs.add(4);
            lhs.add(2);
            System.out.println(lhs);        //[3, 1, 5, 4, 2]
    }

四、TreeSet

4.1 介绍

  • TreeSet是Set集合的实现类,也是元素不重复

  • 底层是基于TreeMap实现的,TreeMap底层是基于红黑树(是一种特殊的二叉树)

  • 会对存储的元素进行排序,默认按照自然顺序排序;或者是通过根据构造方法传入的比较器进行排序

4.2 方法api

仅介绍特殊方法

public static void main(String[] args) {
    TreeSet<Integer> set = new TreeSet<>( );
​
    // 去重,且默认是自然顺序排序
    set.add(31);
    set.add(13);
    set.add(15);
    set.add(41);
    set.add(11);
    set.add(21);
    System.out.println(set );
    Integer ceiling = set.ceiling(15);    //返回set中大于等于给定的最小元素
    System.out.println("ceiling = " + ceiling );
​
    Integer higher = set.higher(15);      //返回set中严格大于给定元素的最小元素
    System.out.println("higher = " + higher);
}

4.3 排序+去重原理

通过向TreeSet<Studnet>中添加Student对象,发现会报错, 提示无法将Student转换成Comparable接口

  • 从而发现,之前Integer,String等类能排序是因为它们实现Comparable接口,并且重写comparTo的方法

  • 发现这个方法返回值决定了顺序和去重

    • 当前(this)比指定小(o), 将其(this)放左树杈, 即返回负数,将数据放在左边

    • 当前(this)比指定大(o), 将其(this)放右树杈,即返回正数,将数据放在右边

    • 当前(this)等于指定(o), 0 不放,即返回0,不往树上放,则去除

package com.qf.set;
public class Student implements Comparable<Student>{
    private int age;
    private String name;
    
    // set get 构造 toString 省略...
    @Override
    public int compareTo(Student o) {
        int n;
        if (this.age == o.getAge() && this.name.equals(o.getName())){
            n = 0;                            //返回0则去重
        } else if (this.age >= o.getAge()){
            n = 1;                            //返回正数放节点右边
        } else {
            n = -1;                           //返回负数放节点左边
        }
        return  n;
    }
}

4.4 比较器排序

new TreeSet() 空参的,默认是使用原始的自然排序,

new TreeSet(Comparator c), 构造方法传入比较器,就会根据比较器排序

// 自定义比较器类,完成对整数倒序排序

public class MyIntegerComparator implements Comparator<Integer> {
    /**
     * o1 就是当前正在存储的
     * o2 就是之前存储的
     */
    @Override
    public int compare(Integer o1, Integer o2) {
        System.out.println("o1 = " + o1);
        System.out.println("o2 = " + o2);
        return o2 - o1;
    }
}
// 测试

public class Demo9 {
​
    public static void main(String[] args) {
​
        // 演示1: 创建自定义比较器类对象
        //TreeSet<Integer> set = new TreeSet<>(new MyIntegerComparator());
       
        // 演示2: 改写成匿名内部类写法
        // TreeSet<Integer> set =
        //         new TreeSet<>(new Comparator<Integer>( ) {
        //             @Override
        //             public int compare(Integer o1, Integer o2) {
        //                 return o2 - o1;
        //             }
        //         });
​
                new TreeSet<>((o1,o2) -> o2 - o1);
        set.add(3);
        set.add(2);
        set.add(5);
        set.add(1);
        set.add(4);
​
        System.out.println(set );
    }
}

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值