【DS】HashSet 详解

在这里插入图片描述

当年面试问的最多的那批 Java 集合框架现在问的还多么? 编程十年(手动狗头) , 我把这些集合框架做成盲盒, 无论你多难, 我都想去了解你, 今天来看-----pia~,HashSet , 基于哈希表实现,存储唯一元素,无序。适用于快速查找、去重操作。常用于集合操作、数据唯一性校验。

一. Set

Set 的官方文档

Set 与 Map 主要的不同有两点:Set 是继承自 Collection 的接口类,Set 中只存储了 Key 。

常见方法说明

在这里插入图片描述

注意:

  1. Set 是继承自 Collection 的一个接口类
  2. Set 中只存储了 key,并且要求 key 一定要唯一
  3. TreeSet 的底层是使用 Map 来实现的,其使用 key 与 Object 的一个默认对象作为键值对插入到 Map 中的
  4. Set 最大的功能就是对集合中的元素进行去重
  5. 实现 Set 接口的常用类有 TreeSet 和 HashSet ,还有一个 LinkedHashSet ,LinkedHashSet 是在 HashSet 的基础上维护了一个双向链表来记录元素的插入次序。
  6. Set 中的 Key 不能修改,如果要修改,先将原来的删除掉,然后再重新插入
  7. TreeSet 中不能插入 null 的 key ,HashSet 可以, 因为 TreeSet 中的 key 需要进行比较, 而 HashSet 中的 key 不需要
  8. TreeSet 和 HashSet 的区别

在这里插入图片描述

二. HashSet

1. HashSet 部分源码

属性:

    private transient HashMap<E,Object> map;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

构造函数:

    public HashSet() {
        map = new HashMap<>();
    }

    /**
     * Constructs a new set containing the elements in the specified
     * collection.  The <tt>HashMap</tt> is created with default load factor
     * (0.75) and an initial capacity sufficient to contain the elements in
     * the specified collection.
     *
     * @param c the collection whose elements are to be placed into this set
     * @throws NullPointerException if the specified collection is null
     */
    public HashSet(Collection<? extends E> c) {
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }

    /**
     * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
     * the specified initial capacity and the specified load factor.
     *
     * @param      initialCapacity   the initial capacity of the hash map
     * @param      loadFactor        the load factor of the hash map
     * @throws     IllegalArgumentException if the initial capacity is less
     *             than zero, or if the load factor is nonpositive
     */
    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }

    /**
     * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has
     * the specified initial capacity and default load factor (0.75).
     *
     * @param      initialCapacity   the initial capacity of the hash table
     * @throws     IllegalArgumentException if the initial capacity is less
     *             than zero
     */
    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }

由这几个构造函数就可以看出, HashSet 的底层还是 HashMap
(所以想要了解 HashMap 和 哈希表 的话可以自取 HashMap哈希表)

在这里插入图片描述

从图中可以看出 HashSet 只是利用了 HashMap 的 key, 而 value 的话是放进去一个统一固定的值。

2. HashSet 的使用

HashSet 的常用方法便是从 Set 实现的那几个常用方法

在这里插入图片描述

    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        list.add("abc");
        list.add("xyz");
        list.add("uvw");
        Set<String> hashSet = new HashSet<>();

        // 放置元素
        hashSet.add("hello");
        hashSet.add("abc");
        hashSet.add("the");
        hashSet.add("world");
        System.out.println(hashSet);

        // 将一个集合中的元素全部加入到 set 中
        hashSet.addAll(list);

        System.out.println(hashSet);


        // 判断 key 值是否存在
        System.out.println(hashSet.contains("hello"));
        System.out.println(hashSet.contains("hello2"));


        // 删除元素
        hashSet.remove("world");
        String[] arr = new String[7];
        // set 转数组
        hashSet.toArray(arr);
        for (String s : arr) {
            System.out.print(s + " ");
        }
    }

三. TreeSet

1. 部分源码

    /**
     * Constructs a new, empty tree set, sorted according to the
     * natural ordering of its elements.  All elements inserted into
     * the set must implement the {@link Comparable} interface.
     * Furthermore, all such elements must be <i>mutually
     * comparable</i>: {@code e1.compareTo(e2)} must not throw a
     * {@code ClassCastException} for any elements {@code e1} and
     * {@code e2} in the set.  If the user attempts to add an element
     * to the set that violates this constraint (for example, the user
     * attempts to add a string element to a set whose elements are
     * integers), the {@code add} call will throw a
     * {@code ClassCastException}.
     */
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }

    /**
     * Constructs a new, empty tree set, sorted according to the specified
     * comparator.  All elements inserted into the set must be <i>mutually
     * comparable</i> by the specified comparator: {@code comparator.compare(e1,
     * e2)} must not throw a {@code ClassCastException} for any elements
     * {@code e1} and {@code e2} in the set.  If the user attempts to add
     * an element to the set that violates this constraint, the
     * {@code add} call will throw a {@code ClassCastException}.
     *
     * @param comparator the comparator that will be used to order this set.
     *        If {@code null}, the {@linkplain Comparable natural
     *        ordering} of the elements will be used.
     */
    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }

    /**
     * Constructs a new tree set containing the elements in the specified
     * collection, sorted according to the <i>natural ordering</i> of its
     * elements.  All elements inserted into the set must implement the
     * {@link Comparable} interface.  Furthermore, all such elements must be
     * <i>mutually comparable</i>: {@code e1.compareTo(e2)} must not throw a
     * {@code ClassCastException} for any elements {@code e1} and
     * {@code e2} in the set.
     *
     * @param c collection whose elements will comprise the new set
     * @throws ClassCastException if the elements in {@code c} are
     *         not {@link Comparable}, or are not mutually comparable
     * @throws NullPointerException if the specified collection is null
     */
    public TreeSet(Collection<? extends E> c) {
        this();
        addAll(c);
    }

    /**
     * Constructs a new tree set containing the same elements and
     * using the same ordering as the specified sorted set.
     *
     * @param s sorted set whose elements will comprise the new set
     * @throws NullPointerException if the specified sorted set is null
     */
    public TreeSet(SortedSet<E> s) {
        this(s.comparator());
        addAll(s);
    }

由源码可以看出 TreeSet 底层是 TreeMap
(想了解 TreeMap 的可以自取 -> TreeMap

2. TreeSet 使用

TreeSet与 HashSet 使用都差不多, 只不过 TreeSet底层是一颗红黑树(一种特殊的二叉搜索树), 是 关于 key 有序的, 所以存放到 TreeSet 里面的 key 必须是能够比较的。所以如果 key 是自定义类型的话, 需要实现 Comparable 接口, 或者 实现一个比较器。(Comparable、比较器)

    public static void main(String[] args) {

        List<String> list = new ArrayList<>();
        list.add("abc");
        list.add("xyz");
        list.add("uvw");
        Set<String> treeSet = new TreeSet<>();

        // 放置元素
        treeSet.add("hello");
        treeSet.add("abc");
        treeSet.add("the");
        treeSet.add("world");
        System.out.println(treeSet);

        // 将一个集合中的元素全部加入到 set 中
        treeSet.addAll(list);

        System.out.println(treeSet);


        // 判断 key 值是否存在
        System.out.println(treeSet.contains("hello"));
        System.out.println(treeSet.contains("hello2"));


        // 删除元素
        treeSet.remove("world");
        String[] arr = new String[7];
        // set 转数组
        treeSet.toArray(arr);
        for (String s : arr) {
            System.out.print(s + " ");
        }
    }

同样的代码, 只是一个是用 HashSet 存储, 一个用 TreeSet 存储, 遍历的结果便不一样

在这里插入图片描述

在这里插入图片描述

上图只是简单的画了一下怎么存储(如果画错了请见谅, 因为它底层是红黑树,确实有点复杂, 中间涉及到了旋转 )。
因为它是二叉搜索树, 所以它的中序遍历就是有序的。

好啦,以上就是对 HashSet 的讲解, 希望能帮到你 !
评论区欢迎指正 !

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值