天天看点

轻松解读源码系列之Java集合抽象类(4)AbstractQueue&AbstractSet

作者:程序员xiao熊

大家好,我是程序员xiao熊,本篇内容将为大家分享Java集合接口Set和Queue的基础实现类:AbstractSet和AbstractQueue;本篇包含内容如下:

1. AbstractSet

1.1 AbstractSet介绍

1.2 方法说明

1.3 方法解析

2. AbstractQueue

2.1 AbstractQueue介绍

2.2 方法说明

3. 扩展阅读

1、AbstractSet

1.1、AbstractSet介绍

AbstractSet实现了Set接口,并继承了AbstractCollection,是Set接口的基础实现,最大限度地降低了实现Set接口的要求;其继承结构图如下:

轻松解读源码系列之Java集合抽象类(4)AbstractQueue&AbstractSet

AbstractSet继承结构图

通过继承AbstractSet来实现Set接口与通过继承AbstractCollection来实现Collection接口类似,除了AbstractSet的子类实现必须遵循Set接口的规范,例如add方法不能允许将一个对象的多个实例添加到一个集合中

需要注意的是,该类不会覆盖AbstractCollection类的任何实现。它只是添加了equals和hashCode的实现;此外,AbstractSet覆盖了removeAll方法,其特点是始终只遍历元素最小的集合来删除元素

1.2、方法说明

AbstractSet只是添加了equals、hashCode、removeAll的实现

boolean equals(Object o) 比较指定对象与此集合是否相等。如果指定对象也是一个集合,两个集合的大小相同,并且指定集合的每个成员都包含在这个集合中(或者等价地说,这个集合的每个成员都包含在指定集合中),返回true;这个定义确保了equals方法的逻辑在set接口的不同实现中都是正确的;
int hashCode() 返回此集合的哈希码值。集合的哈希码定义为集合中元素的哈希码之和,其中null元素的哈希码定义为零。这确保了对于任意两个集合s1和s2, s1.equals(s2)意味着s1. hashcode ()==s2. hashcode(),这符合Object.hashCode()的一般约定。
boolean removeAll(Collection<?> c) 删除当前集合中存在于指定集合中的元素;如果当前集合于指定的集合有交集,则返回true(说明当前集合会发生变化);否则返回false;

1.3、方法解析

本小节只讲解removeAll方法,因为其特点是始终只遍历元素最小的集合来删除元素,保证性能最优,具体业务逻辑过程如下:

1. 入参集合的非空校验

2. 如果入参集合比当前集合小,则遍历入参集合,从当前集合中删除元素

3. 如果入参集合比当前集合大,则遍历当前集合,使用iterator删除元素

public boolean removeAll(Collection<?> c) {
    // 1.	入参集合的非空校验
    Objects.requireNonNull(c);
    boolean modified = false;

    // 2.	如果入参集合比当前集合小,则遍历入参集合,从当前集合中删除元素
    if (size() > c.size()) {
        for (Iterator<?> i = c.iterator(); i.hasNext(); )
            modified |= remove(i.next());
    } else {
       // 3. 如果入参集合比当前集合大,则遍历当前集合,使用iterator删除元素
        for (Iterator<?> i = iterator(); i.hasNext(); ) {
            if (c.contains(i.next())) {
                i.remove();
                modified = true;
            }
        }
    }
    return modified;
}
           

2、AbstractQueue

2.1、AbstractQueue介绍

AbstractQueue类实现了Queue接口,并继承了AbstractCollection, 提供了一些队列操作的基本实现。当基础实现不允许null元素时,这个类中的实现是合适的。AbstractQueue的继承结构图如下:

轻松解读源码系列之Java集合抽象类(4)AbstractQueue&amp;AbstractSet

AbstractQueue继承结构图

  • 具备的特性
  1. add、remove和element方法分别对应offer、poll和peek,但会抛出异常,而不是返回false或null表示失败。具体如下:
队列方法总结
抛出异常 返回固定的值
Insert操作 add(e) offer(e)
Remove操作 remove() poll()
Examine操作(检索元素) element() peek()
  1. 继承这个类的队列实现必须至少定义一个Queue.offer(E)方法,该方法不允许插入null元素,此外还需要实现Queue.peek()、Queue.poll()、Collection.size()和Collection.iterator()方法。通常,其他方法也会被覆盖。如果不需要实现这些方法,则考虑继承AbstractCollection。

2.2、方法说明

AbstractQueue的方法说明如下表所示;该类只提供了以下方法的实现,其中clear()方法通过poll()操作清除元素,addAll方法依赖add方法;而add、element、remove分别依赖于offer、peek、poll方法,具体的子类需要实现offer、peek、poll方法

boolean add(E e) 元素进入队列尾部
boolean addAll(Collection<? extends E> c) 批量元素进入队列
void clear() 清除队列的元素
E element() 返回队列头部的元素,但是不删除
E remove() 返回队列头部的元素,并且删除

3、扩展阅读

更多关于Java集合的内容,可参考以下文章:

轻松解读源码系列之Java集合接口&抽象类(1)—Map和Collection

轻松解读源码系列之Java集合接口&抽象类(2)—AbstractCollection

轻松解读源码系列之Java集合接口&抽象类(3)—List、Set、Queue

轻松解读源码系列之Java集合接口&抽象类(4)—AbstractList

轻松解读源码系列之Java集合ArrayList(上)

轻松解读源码系列之Java集合ArrayList(下)

轻松解读源码系列之Java集合LinkedList(上)

轻松解读源码系列之Java集合LinkedList(中)

轻松解读源码系列之Java集合LinkedList(下)

轻松解读源码系列之ArrayList和LinkedList总结

今天的分享就到这里,欢迎大家在评论区进行交流

继续阅读