Java collection framework-Set

Preface

Set is a subclass of the collection interface Collection. The simple structure diagram of the commonly used implementation classes of this interface is as follows:
Insert picture description here
Next, we will introduce the implementation classes in the figure above in turn:

1. HashSet class

Let's first look at the source code of HashSet, and analyze and introduce some of its contents:

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;
    }

}

The underlying implementation of hashSet is HashMap, so most of the methods and usage of HashSet are the same as HashMap. For the principle of HashMap, you can refer to another blog: Java Collection Framework-Map

2, LinkedHashSet class

The LinkedHashSet class is a subclass of HashSet. The following is part of the source code of 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);
    }
}

As can be known from the LinkedHashSet source code, LinkedHashSet is a subclass of HashSet, and its construction method follows the construction method of the parent class, but all the construction methods are a default method in the parent class used:

    /**
     * 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);
    }

It can be seen that the underlying implementation of LinkedHashSet is LinkedHashMap, so as long as you understand LinkedHashMap, you can refer to the blog for the principle and related content of LinkedHashMap: Java Collection Framework-Map

3. TreeSet class

First come to the source code, the following is part of the source code content, take a look at the implementation of the TreeSet class:

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);
    }
 }

The underlying implementation of TreeSet is TreeMap, and most of the methods are methods in the walked TreeMap, so you can refer to the introduction of the TreeMap section in the blog; blog post address: Java collection framework-Map

The difference between TreeSet and the above two implementation classes is that TressSet can control the order of data in the Set through a comparator. You can use the default comparator or implement the comparator yourself.

4. Introduction to the use of implementation classes in Set

Next, we will introduce the simple use of several implementation classes introduced above:

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);
		}
	}
}

The output is:

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

Guess you like

Origin blog.csdn.net/qgnczmnmn/article/details/108584322