Java集合总结二[Set篇]

本文详细介绍了Java中的HashSet、TreeSet和LinkedHashSet三种集合类,包括它们的实现原理、特性(如无序/有序、去重、线程安全等)、构造方法和主要操作方法,适合理解和使用这些集合在实际项目中的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

HashSet

public class HashSet<E>
    extends AbstractSet<E>
    implements Set<E>, Cloneable, java.io.Serializable

特征

基于HashMap实现,无容量限制

不保证集合的迭代顺序(顺序依据hash值)

允许空元素(null),但只能放入一个null

实现不同步(线程不安全)

如果在创建迭代器后的任何时间修改集合,则除了通过迭代器自己的 remove 方法之外,都throw

数据结构

        哈希表

//由哈希表(实际上是 HashMap 实例)提供支持
private transient HashMap<E,Object> map;
// Dummy value to associate with an Object in the backing Map
//用于与底层map中的对象关联
private static final Object PRESENT = new Object();

构造方法

    //无参构造
    public HashSet() {
        map = new HashMap<>();
    }
    //有参构造(初始容量)
    public HashSet(int initialCapacity) {
        map = new HashMap<>(initialCapacity);
    }
    //有参(初始容量, hash映射的负载系数) 后面会说loadFactor(此处可忽略)
    public HashSet(int initialCapacity, float loadFactor) {
        map = new HashMap<>(initialCapacity, loadFactor);
    }

添加操作

    //元素E作为map集合中的Key值, key值不唯一
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

删除操作

    public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }

遍历操作

    //获取迭代器
    public Iterator<E> iterator() {
        return map.keySet().iterator();
    }
    //通过循环遍历每一个元素
    while (iterator.hasNext()){
        Object element= iterator.next();
    }
    

使用场景

按照Hash算法来实现元素的查找和存储的

去重、快速查找或随机元素

去重

        需要重写对象的equals和hashCode

        注意:如果只重写equls方法, 不重写hashCode方法, 在HashSet去重中,最终的HashSet中应该只保留1个对象,即最终输出的HashSet的size为1,但是我们得到的结果却是2

快速查找

        由于HashSet的元素是经过哈希计算的,因此可以通过哈希表快速进行查找操作

随机元素

        由于HashSet中的元素是无序的,因此可以通过随机获取HashSet中的元素来实现随机数的操作

Set setOfNumbers = new HashSet<>(Arrays.asList(1, 2, 3, 4, 5));
int randomIndex = new Random().nextInt(setOfNumbers.size());
Iterator iterator = setOfNumbers.iterator();
int i = 0;
while(iterator.hasNext()){
 int number = iterator.next();
 if (i == randomIndex){
 System.out.println("Random number: " + number);
 break;
 }
    i++;
}
//参考: https://www.zhihu.com/question/401606017

TreeSet

public class TreeSet<E> extends AbstractSet<E>
    implements NavigableSet<E>, Cloneable, java.io.Serializable

特征

不允许空元素(null)

元素有序(排序)

实现不同步(线程不安全)

数据结构

       红黑树(平衡二叉树)

    //map
    private transient NavigableMap<E,Object> m;
    // Dummy value to associate with an Object in the backing Map
    //同HashSet的PRESENT
    private static final Object PRESENT = new Object();

构造方法

    //无参构造
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }
    //有参构造(比较器)
    public TreeSet(Comparator<? super E> comparator) {
        this(new TreeMap<>(comparator));
    }

        (1)无参方法中, 比较器为null.

        Element 类 可以通过实现Comparable接口, 重写compareTo()方法实现排序 

        compareTo返回值 1是前者权重大,-1是后者权重大。按照权重由小到大排序

                this在前表示升序

                o在前表示降序

                this.成员变量1.compareTo(o.成员变量1) == 0 ? 

                this.成员变量2.compareTo(o.成员变量2) :

                this.成员变量1.compareTo(o.成员变量1)

                //表示首排序为成员变量1, 次排序为成员变量2.

        举例:
        return this.id.compareTo(student.id) == 0 ?
                this.name.compareTo(student.name) :
                this.id.compareTo(student.id);

       (2)有参方法中使用Compatator的匿名内部类, 实现compare(O1, O2)方法

                o1 - o2 升序

                o2 - o1 降序

添加操作

    public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }
    //
    public  boolean addAll(Collection<? extends E> c) {
        // Use linear-time version if applicable
        if (m.size()==0 && c.size() > 0 &&
            c instanceof SortedSet &&
            m instanceof TreeMap) {
            SortedSet<? extends E> set = (SortedSet<? extends E>) c;
            TreeMap<E,Object> map = (TreeMap<E, Object>) m;
            Comparator<?> cc = set.comparator();
            Comparator<? super E> mc = map.comparator();
            if (cc==mc || (cc != null && cc.equals(mc))) {
                map.addAllForTreeSet(set, PRESENT);  //map方法
                return true;
            }
        }
        return super.addAll(c);
    }

删除操作

    public boolean remove(Object o) {
        return m.remove(o)==PRESENT;
    }

遍历操作

    public Iterator<E> iterator() {
        return m.navigableKeySet().iterator();
    }

使用场景

排序, 元素需要排序使用TreeSet

LinkedHashSet

public class LinkedHashSet<E>
    extends HashSet<E>
    implements Set<E>, Cloneable, java.io.Serializable 

特征

具有迭代顺序

实现不同步(线程不安全)

继承自HashSet, 底层是LinkedHashMap

没有重复的元素

数据结构

哈希表和双向链表实现

构造方法

    //无参构造
    public LinkedHashSet() {
        super(16, .75f, true);
    }
    //有参构造(初始化容量)
    public LinkedHashSet(int initialCapacity) {
        super(initialCapacity, .75f, true);
    }
    //有参构造(初始化容量, 负载因子)
    public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值