没长正的技术专栏 勤动手、多思考

常用集合-Set

2017-01-04

阅读:


常用集合-Set

介绍常用集合Set的特点、线程安全问题、实现线程安全的方式。

### Set

#### 不安全的子类 EnumSetTreeSetHashSetLinkedHashSetNavigableSet

##### EnumSet EnumSet是枚举类型的容器,是一个抽象类,非线程安全,继承了AbstractSet

/**
 * @author Josh Bloch
 * @since 1.5
 * @see EnumMap
 * @serial exclude
 */
public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
    implements Cloneable, java.io.Serializable
{
	/**
     * Creates an empty enum set with the specified element type.
     *
     * @param <E> The class of the elements in the set
     * @param elementType the class object of the element type for this enum
     *     set
     * @return An empty enum set of the specified type.
     * @throws NullPointerException if <tt>elementType</tt> is null
     */
    public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
        Enum<?>[] universe = getUniverse(elementType);
        if (universe == null)
            throw new ClassCastException(elementType + " not an enum");

        if (universe.length <= 64)
            return new RegularEnumSet<>(elementType, universe);
        else //超过64则创建JumboEnumSet
            return new JumboEnumSet<>(elementType, universe);
    }
	...
}

​ 内部提供静态方法noneOf(Enum.class clazz)来创建一个实现了继承自EnumSet类的实例,如果要装载的枚举类值不超过64个,则创建的是RegularEnumSet实例,如果超过64位,则创建的是JumboEnumSet。

RegularEnumSet内部通过Bit数组来存放枚举值,而这个Bit数组其实就是一个Long类型数值,初试时是0L,添加元素时,是把对应枚举元素的ordinal(每一个枚举类的枚举值都对应一个ordinal值)值映射到64Bit上的某一个位置为1。因为Set是不能重复的,所以RegularEnumSet最多存64个元素,RegularEnumSet的add方法源码如下:

public boolean add(E e) {
    typeCheck(e);
    long oldElements = elements;
    elements |= (1L << ((Enum<?>)e).ordinal());
    return elements != oldElements;
}

JumboEnumSet内部则通过Long数组类存放枚举值,所以可以存放远远大于64个元素,当然枚举值太多也没有意义。

TreeSet

​ treeSet是有序集合。

/**
 * @author  Josh Bloch
 * @see     Collection
 * @see     Set
 * @see     HashSet
 * @see     Comparable
 * @see     Comparator
 * @see     TreeMap
 * @since   1.2
 */
public class TreeSet<E> extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, java.io.Serializable{
    public TreeSet() {
        this(new TreeMap<E,Object>());
    }
	...
}

​ 内部通过TreeMap来存储元素,把元素存储在map的key里,通过TreeMap存储Key的有序性和无重复性来实现自己的有序性和Set的的元素无重复性;插入元素时,会根据元素的equals和compareTo方法判断大小,然后进行排序,但也只是插入的时候会进行排序,插入后修改顺序不改变。


欢迎拍砖,多多交流,转载请注明出处:[没长正的技术专栏](http://blog.meizhangzheng.com) 如涉及侵权问题,请发送邮件到xsj34567@163.com,如情况属实本人将会尽快删除。


上一篇 基本变量类型

Comments

Content