java 集合(3):Set 集合

Set集合

Set集合类似于一个罐子,程序可以依次把多个对象“丢进”Set集合,而Set集合通常不能记住元素的添加顺序。实际上Set就是Collection只是行为略有不同(Set不允许包含重复元素)。

  • Set集合不允许包含相同的元素,如果试图把两个相同元素加入同一个Set集合中,则添加操作失败,add()方法返回false,且新元素不会被加入。
  • Set集合,继承自Collection。特征是插入无序,不可指定位置访问。
  • Set集合的实现类可说是基于Map集合去写的。通过内部封装Map集合来实现的。比如HashSet内部封装了HashMap。
  • Set集合的数据库不能重复(== 或 eqauls)的元素。
  • Set集合的常用实现类有 HashSet、TreeSet

HashSet类(多线程不安全)

HashSet 是 Set 接口的典型实现,大多数时候使用 Set 集合时就是使用这个实现类。HashSet 按 Hash 算法来存储集合中的元素,因此具有很好的存取和查找性能。底层数据结构是哈希表。

  • 不能保证元素的排列顺序,顺序可能与添加顺序不同,顺序也可能发生变化;
  • HashSet不是同步的;
  • 集合元素值可以是null;

哈希表: 一个元素为链表的数组,综合了数组与链表的优点。

当向 HashSet 集合中存入一个元素时,HashSet会调用该对象的hashCode方法来得到该对象的hashCode值,然后根据该hashCode值决定该对象在HashSet中的存储位置。

  • 如果有两个元素通过equals方法比较true,但它们的hashCode方法返回的值不相等,HashSet将会把它们存储在不同位置,依然可以添加成功。
  • 也就是说。HashSet集合判断两个元素的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode方法返回值也相等。即:靠元素重写hashCode方法和equals方法来判断两个元素是否相等,如果相等则覆盖原来的元素,以此来确保元素的唯一性。

HashSet的优势

  • 因为数组的索引是连续的而且数组的长度是固定的,无法自由增加数组的长度。而HashSet就不一样了,HashCode表用每个元素的hashCode值来计算其存储位置,从而可以自由增加HashCode的长度
  • 并根据元素的hashCode值来访问元素。而不用一个个遍历索引去访问,这就是它比数组快的原因。
  • HashCode中每个存储元素的“槽位”通常称为“桶”,如果多个元素的hashCode值相同,但它们通过equals方法比较返回false,就需要在桶里放多个元素,这样会导致性能下降。

LinkedHashSet类

HashSet 还有一个子类 LinkedList、LinkedHashSet 集合也是根据元素的 hashCode 值来决定元素的存储位置,但它同时使用链表维护元素的次序,这样使得元素看起来是以插入的顺序保存的,也就是说当遍历集合 LinkedHashSet 集合里的元素时,集合将会按元素的添加顺序来访问集合里的元素。

输出集合里的元素时,元素顺序总是与添加顺序一致。但是LinkedHashSet 依然是 HashSet,因此它不允许集合重复。

TreeSet类

TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。

内部存储机制

TreeSet内部实现的是红黑树,默认整形排序为从小到大。
在这里插入图片描述

EnumSet类

EnumSet类的特征:

  • EnumSet是一个专门为枚举类设计的集合类,EnumSet中的所有元素都必须是指定枚举类型的枚举值,该枚举类型在创建EnumSet时显式或隐式地指定。
  • EnumSet的集合元素也是有序的,EnumSet以枚举值在Enum类内的定义顺序来决定集合元素的顺序。
  • EnumSet在内部以位向量的形式存储,这种存储形式非常紧凑、高效,因此EnumSet对象占用内存很小,而且运行效率很好。
  • EnumSet集合不允许加入null元素。
  • EnumSet类没有暴露任何构造器来创建该类的实例,

EnumSet 类提供了以下类方法来创建 EnumSet 对象。

  • EnumSet allOf(Class elementType):创建一个包含指定枚举类里所有枚举值的 EnumSet 集合。
  • EnumSet complementOf(EnumSet s):创建一个其元素类型与指定EnumSet里元素类型相同的 EnumSet 集合,新的集合里包含原集合不包含的枚举值。
  • EnumSet copyOf(Collection c):使用一个普通集合来创建 EnumSet 集合;
  • EnumSet copyOf(EnumSet s):复制原集合;
  • EnumSet noneOf(Class elementType):创建一个元素类型为指定枚举类型的空EnumSet;
  • EnumSet of(E first,E…rest):创建一个包含一个或多个枚举值的EnumSet集合。传入的枚举值必须是同一枚举类。
  • EnumSet range(E from,E to):创建一个包含从 from 到 to 枚举值范围所有枚举值的 EnumSet 集合。
package com.collection;

import java.util.EnumSet;

public class EnumSetTest {

    public static void main(String[] args) {
        //1.创建一个包含Session(枚举类)里所有枚举值的EnumSet集合
        EnumSet e1 = EnumSet.allOf(Session.class);
        System.out.println(e1);//[SPRING, SUMMER, FAIL, WINTER]

        //2.创建一个空EnumSet
        EnumSet e2 = EnumSet.noneOf(Session.class);
        System.out.println(e2);//[]

        //3. add()空EnumSet集合中添加枚举元素
        e2.add(Session.SPRING);
        e2.add(Session.SUMMER);
        System.out.println(e2);//[SPRING, SUMMER]

        //4. 以指定枚举值创建EnumSet集合
        EnumSet e3 = EnumSet.of(Session.SPRING,Session.FAIL);
        System.out.println(e3);//[SPRING, FAIL]

        //5.创建一个包含从from枚举值到to枚举值范围内所有枚举值的EnumSet集合。
        EnumSet e4 = EnumSet.range(Session.SPRING,Session.FAIL);
        System.out.println(e4);//[SPRING, SUMMER, FAIL]

        //6.创建一个其元素类型与指定EnumSet里元素类型相同的EnumSet集合,
        //  新EnumSet集合包含原EnumSet集合所不包含的枚举值
        EnumSet e5 = EnumSet.complementOf(e4);
        System.out.println(e5);//[WINTER]
    }
}

//创建一个枚举
enum Session{
    SPRING,
    SUMMER,
    FAIL,
    WINTER
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值