Javaコレクションフレームワークセット

序文

Setは、コレクションインターフェイスCollectionのサブクラスです。このインターフェイスの一般的に使用される実装クラスの簡単な構造図は次のとおりです。
ここに画像の説明を挿入
次に、上の図の実装クラスを順に紹介します。

1. HashSetクラス

最初にHashSetのソースコードを見て、その内容のいくつかを分析して紹介しましょう。

public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable
{
    
    
    private transient HashMap<E,Object> map;

	/**
		由源码可知,HashSet共有四个构造函数,底层的实现实为HashMap
	*/
    public HashSet() {
    
    
        map = new HashMap<>();
    }
    public HashSet(Collection<? extends E> c) {
    
    
        map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
        addAll(c);
    }
    public HashSet(int initialCapacity, float loadFactor) {
    
    
        map = new HashMap<>(initialCapacity, loadFactor);
    }
    public HashSet(int initialCapacity) {
    
    
        map = new HashMap<>(initialCapacity);
    }
    HashSet(int initialCapacity, float loadFactor, boolean dummy) {
    
    
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
    }

	// 返回为HashMap中所有key的迭代器
    public Iterator<E> iterator() {
    
    
        return map.keySet().iterator();
    }


    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();
	/**
	* 添加数据这个地方有一点特殊,HashSet只使用了HashMap中的键列(key),
	* 对于value,则使用一个空的Object对象来填充。
	*/
    public boolean add(E e) {
    
    
        return map.put(e, PRESENT)==null;
    }

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

}

hashSetの基本的な実装はHashMapであるため、HashSetのほとんどのメソッドと使用法はHashMapと同じです。HashMapの原理については、別のブログを参照してください:Java Collection Framework-Map

2、LinkedHashSetクラス

LinkedHashSetクラスはHashSetのサブクラスで、LinkedHashSetのソースコードの一部です。

public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, java.io.Serializable {
    
    
    public LinkedHashSet(int initialCapacity, float loadFactor) {
    
    
        super(initialCapacity, loadFactor, true);
    }
    public LinkedHashSet(int initialCapacity) {
    
    
        super(initialCapacity, .75f, true);
    }
    public LinkedHashSet() {
    
    
        super(16, .75f, true);
    }
    public LinkedHashSet(Collection<? extends E> c) {
    
    
        super(Math.max(2*c.size(), 11), .75f, true);
        addAll(c);
    }

    @Override
    public Spliterator<E> spliterator() {
    
    
        return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
    }
}

LinkedHashSetソースコードからわかるように、LinkedHashSetはHashSetのサブクラスであり、その構築メソッドは親クラスの構築メソッドに従いますが、すべての構築メソッドは使用される親クラスのデフォルトメソッドです。

    /**
     * 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<>(initialCapacity, loadFactor);
    }

LinkedHashSetの基礎となる実装はLinkedHashMapであることがわかります。LinkedHashMapを理解している限り、LinkedHashMapの原理と関連コンテンツについてブログを参照できます。JavaCollection Framework-Map

3. TreeSetクラス

まずソースコードに来ると、以下はソースコードコンテンツの一部です。TreeSetクラスの実装を見てください。

public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable
{
    
    
    /**
     * The backing map.
     */
    private transient NavigableMap<E,Object> m;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

    /**
     * Constructs a set backed by the specified navigable map.
     */
    TreeSet(NavigableMap<E,Object> m) {
    
    
        this.m = m;
    }

    /**
     *	先来看TreeSet的构造函数,TreeSet的底层实现是基于TreeMap来实现的
     */
    public TreeSet() {
    
    
        this(new TreeMap<E,Object>());
    }
    public TreeSet(Comparator<? super E> comparator) {
    
    
        this(new TreeMap<>(comparator));
    }
    public TreeSet(Collection<? extends E> c) {
    
    
        this();
        addAll(c);
    }
    public TreeSet(SortedSet<E> s) {
    
    
        this(s.comparator());
        addAll(s);
    }


    /**
     * Adds all of the elements in the specified collection to this set.
     *
     * @param c collection containing elements to be added to this set
     * @return {@code true} if this set changed as a result of the call
     * @throws ClassCastException if the elements provided cannot be compared
     *         with the elements currently in the set
     * @throws NullPointerException if the specified collection is null or
     *         if any element is null and this set uses natural ordering, or
     *         its comparator does not permit null elements
     */
    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);
                return true;
            }
        }
        return super.addAll(c);
    }
 }

TreeSetの基本的な実装はTreeMapであり、ほとんどのメソッドはウォークされたTreeMapのメソッドであるため、ブログのTreeMapセクションの紹介を参照できます。ブログ投稿アドレス:Javaコレクションフレームワーク-マップ

TreeSetと上記の2つの実装クラスの違いは、TressSetがコンパレータを介してセット内のデータの順序を制御できることです。デフォルトのコンパレータを使用するか、自分でコンパレータを実装できます。

4. Setでの実装クラスの使用の概要

次に、上記で紹介したいくつかの実装クラスの簡単な使用法を紹介します。

public class Collection_Set {
    
    
	private final static Comparator<String> comparator;
	static {
    
    
		comparator=new Comparator<String>() {
    
    
			@Override
			public int compare(String o1, String o2) {
    
    
				// 倒序排列:o2.compareTo(o1)
				// 正序排列:o1.compareTo(o2)
				return o2.compareTo(o1);
			}
		};
	}

	public static void main(String[] args) {
    
    
		Collection<String> coll=new ArrayList<String>();
		coll.add("河北");
		coll.add("河南");
		coll.add("北京");
		coll.add("广州");
		//coll.add(null);
		System.out.println("hashSet====================");
		// 根据hashCode()计算值来确定值的位置
		// 值可以为null
		Set<String> hashSet=new HashSet<String>(coll); 
		for (String string : hashSet) {
    
    
			System.out.println(string);
		}
		
		System.out.println("treeSet====================");
		// 根据比较器中的策略来确定位置
		// 值不能为null
		Set<String> treeSet=new TreeSet<>(comparator);
		treeSet.addAll(hashSet);
		for (String string : treeSet) {
    
    
			System.out.println(string);
		}
		
		System.out.println("linkedHashSet====================");
		// 默认按照输入的顺序进行存储
		// 值可以为null
		Set<String> linkedHashSet=new LinkedHashSet<>(coll);
		for (String string : linkedHashSet) {
    
    
			System.out.println(string);
		}
	}
}

出力は次のとおりです。

hashSet====================
广州
河北
河南
北京
treeSet====================
河南
河北
广州
北京
linkedHashSet====================
河北
河南
北京
广州

おすすめ

転載: blog.csdn.net/qgnczmnmn/article/details/108584322