java 数据结构与并发之 --- Set

        Set 接口实现的是 Collection接口,公开的方法和Collection的方法完全一致,没有提供特殊的方法,可见Set接口基本没有提供特殊的方法与实现,可见它是在通用的Collection里是提供抽象最为相似的一种集合。AbstractSet 实现了 Set接口,同时继承于 AbstractCollection , 关于AbstractCollection中的方法已经在《java数据结构与并发之--List(基础篇)》里已经做过了介绍,已经实现了Collection接口方法,而Set接口本身没有特殊的方法需要继承,在AbstractSet中只重写了 hashCode 和 equals 方法,另外根据Set本身的特征对removeAll方法进行重写来可能性的提高性能。同时值得注意的是,AbstractSet中并没有iterator()的方法进行实现,也没有扩展出特殊的iterator方法。

        HashSet 和 LinkedHashSet 是我们经常会用到的常用的Set的实现类。我们先看一下HashSet,打开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();

        可以看出 HashSet 内部使用的数据结构全部是使用 HashMap 的实现去完成HashSet的基本功能的, 其中 PERSENT 是保留的一个对象用来填充 HashMap 的时候作为value,其中HashSet中的所有实现方法都依赖于HashMap,以及HashMap中的keySet(另外提一下在Map结构中也存在很多 Set的内部内实现于AbstractSet,这个在具体讲解到 Map 数据结构时再详细讲解),只有以下构造方法:

    /**
     * Constructs a new, empty linked hash set.  (This package private
     * constructor is only used by LinkedHashSet.) The backing
     * HashMap instance is a LinkedHashMap with 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
     * @param      dummy             ignored (distinguishes this
     *             constructor from other int, float constructor.)
     * @throws     IllegalArgumentException if the initial capacity is less
     *             than zero, or if the load factor is nonpositive
     */
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
	map = new LinkedHashMap<E,Object>(initialCapacity, loadFactor);
    }

        此构造方法里使用到了LinkedHashMap, 此方法是包级别调用的,同时此方法为了在程序中多态被调用,居然是用了一个无效的参数,这样如果不看源码,还真不知道这居然是一个无用的参数,dummy无论传入true或者false都是同样的效果(这里并不值得学习)。

        HashSet的内容就是这些,我们来看一下LinkedHashSet:(没有任何的特殊方法,只利用了我们上面说道的调用 LinkedHashMap 的特殊构造方法修改重写所有的HashSet构造方法,让所有的方法都走了 LinkedHashMap的实现。)

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

    private static final long serialVersionUID = -2851667679971038690L;

    /**
     * Constructs a new, empty linked hash set with the specified initial
     * capacity and load factor.
     *
     * @param      initialCapacity the initial capacity of the linked hash set
     * @param      loadFactor      the load factor of the linked hash set
     * @throws     IllegalArgumentException  if the initial capacity is less
     *               than zero, or if the load factor is nonpositive
     */
    public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
    }

    /**
     * Constructs a new, empty linked hash set with the specified initial
     * capacity and the default load factor (0.75).
     *
     * @param   initialCapacity   the initial capacity of the LinkedHashSet
     * @throws  IllegalArgumentException if the initial capacity is less
     *              than zero
     */
    public LinkedHashSet(int initialCapacity) {
        super(initialCapacity, .75f, true);
    }

    /**
     * Constructs a new, empty linked hash set with the default initial
     * capacity (16) and load factor (0.75).
     */
    public LinkedHashSet() {
        super(16, .75f, true);
    }

    /**
     * Constructs a new linked hash set with the same elements as the
     * specified collection.  The linked hash set is created with an initial
     * capacity sufficient to hold the elements in the specified collection
     * and the default load factor (0.75).
     *
     * @param c  the collection whose elements are to be placed into
     *           this set
     * @throws NullPointerException if the specified collection is null
     */
    public LinkedHashSet(Collection<? extends E> c) {
        super(Math.max(2*c.size(), 11), .75f, true);
        addAll(c);
    }
}

        另外同样 Collections中提供了 EmptySet , SynchronizedSet 和 UnmodifiableSet,和 List中同理 EmptySet 是实现一个空的Set, 然后 SynchronizedSet 实现一个同步级的 Set,UnmodifiableSet针对修改的方法实现抛出异常来实现了不允许修改的含义。

        前面的AbstractSet的子类提供的方法几乎没有对Collection接口进行特别的添加,同时java提供了另外一种Set接口: public interface SortedSet<E> extends Set<E>,我们可以看出这种接口继承至Set同时根据类名的意思就是可排序的Set接口,同时它新提供了以下接口方法:

Method Summary
 Comparator<? super E>comparator() 
          Returns the comparator used to order the elements in this set, or null if this set uses the natural orderingof its elements.
 Efirst() 
          Returns the first (lowest) element currently in this set.
 SortedSet<E>headSet(E toElement) 
          Returns a view of the portion of this set whose elements are strictly less than toElement.
 Elast() 
          Returns the last (highest) element currently in this set.
 SortedSet<E>subSet(E fromElement, E toElement) 
          Returns a view of the portion of this set whose elements range from fromElement, inclusive, to toElement, exclusive.
 SortedSet<E>tailSet(E fromElement) 
          Returns a view of the portion of this set whose elements are greater than or equal to fromElement.

        提供了comparator方法,通过comparator内容进行返回相关的排序信息,同时提供了first,last 的获取方法,同时提供了 haedSet,tailSet, subSet 等截取方法,可以看出与List结构不同的是,它全部使用对象做为标记,而没有index概念。TreeSet 继承至SortedSet,java1.6又对SortedSet接口进行了扩展出了NavigableSet接口,TreeSet增加了NavigableSet接口的实现,其中NavigableSet接口多出了以下方法:

Method Summary
 Eceiling(E e) 
          Returns the least element in this set greater than or equal to the given element, or null if there is no such element.
 Iterator<E>descendingIterator() 
          Returns an iterator over the elements in this set, in descending order.
 NavigableSet<E>descendingSet() 
          Returns a reverse order view of the elements contained in this set.
 Efloor(E e) 
          Returns the greatest element in this set less than or equal to the given element, or null if there is no such element.
 NavigableSet<E>headSet(E toElement, boolean inclusive) 
          Returns a view of the portion of this set whose elements are less than (or equal to, if inclusive is true)toElement.
 Ehigher(E e) 
          Returns the least element in this set strictly greater than the given element, or null if there is no such element.
 Elower(E e) 
          Returns the greatest element in this set strictly less than the given element, or null if there is no such element.
 EpollFirst() 
          Retrieves and removes the first (lowest) element, or returns null if this set is empty.
 EpollLast() 
          Retrieves and removes the last (highest) element, or returns null if this set is empty.
 NavigableSet<E>subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) 
          Returns a view of the portion of this set whose elements range from fromElement to toElement.
 SortedSet<E>subSet(E fromElement, E toElement) 
          Returns a view of the portion of this set whose elements range from fromElement, inclusive, to toElement, exclusive.
 NavigableSet<E>tailSet(E fromElement, boolean inclusive) 
          Returns a view of the portion of this set whose elements are greater than (or equal to, if inclusive is true) fromElement.

        接口中多出了更多的和顺序性相关的接口,包括倒序(descending*),临界的(ceiling,floor,higher,lower)最大值,最小值,另外提供了pollFirst, pollLast方法进行取出并删除首尾,同时对headSet,tailSet进行增强,这两个新方法提供了是否包含equals本元素。

        CopyOnWriteArraySet 同样实现了 Set 接口的方法,没有特殊方法接口的开放特殊的方法接口,但是我们可以清晰看到 private final CopyOnWriteArrayList<E> al; 作为CopyOnWriteArraySet内部的数据结构,所有的方法都是通过调用 al 来实现的。具有Set特性的方法,通过CopyOnWriteArrayList提供的 addAllAbsent, addIfAbsent, remove等方法来实现其功能。可以看到CopyOnWriteArraySet 只是使用了 CopyOnWriteArrayList里的几个特有方法实现了Set的功能,其基本的内部原理都还和CopyOnWriteArrayList一样。

        同样 ConcurrentSkipListSet 内不是也是使用的 ConcurrentNavigableMap ,然后构造方法中创建对应的ConcurrentSkipListMap,然后接口功能都是通过ConcurrentNavigableMap相应的方法实现。

        从以上对Set的了解可以看出,Set接口的各种实现类基本都是通过内部对应的Map数据结构来实现,除了CopyOnWriteArraySet 使用了之前分析过的 CopyOnWriteArrayList做为内部数据结构进行实现的。分析Set的并发情况,其基本并发情况跟在说List中的情况基本一致,HashSet , LinkedHashSet, TreeSet 线程非安全,不适合多线程下被多个线程使用,多线程下的Set考虑使用 Collections.SynchronizedSet , CopyOnWriteArraySet ,其中CopyOnWriteArraySet 读操作频繁,写操作较少的情况下性能较高。Collections.UnmodifiableSet 用于在确定不让此数据结构不能修改的情况下使用,基本理论和List并发情况的论述中是一致的。


转载于:https://my.oschina.net/u/1993946/blog/306127

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值