Set集合是如何保證元素不重復的?


      我們都知道Set容器中的元素是無序不重復的,那么Set集合是怎么保證元素不重復的呢?Set是一個接口,

HashSet是Set接口的具體實現,以HashSet為例,來看一下它的具體實現。

     先來看一下HashSet源碼中的的幾個構造器:

private transient HashMap<E,Object> map;

    private static final Object PRESENT = new Object();//注意這個變量,待會會用到
  

  //這個是經常使用到的構造器,可以發現無論是哪一個構造器,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的add方法的源碼:

public boolean add(E e) {
     //PRESENT是一個虛擬值,是為了HashMap實現HashSet的一個假設的值
return map.put(e, PRESENT)==null; }

  當HashSet進行add操作時,其實是將要add的元素作為map的key,將PRESENT這個對象作為map的value,存入map中,並且需要注意到add方法的返回值是一個boolean。

      其實到這里,我們應該能明白為什么HashSet中的元素不能重復了:

                  因為HashSet的底層是由HashMap實現的,而HashSet的add方法,是將元素作為map的key進行存儲的,map的key是不會重復的,所以HashSet中的元素也不會重復。

 

 接下來看個例子:

public static void main(String[] args) {
        Set<Object> set = new HashSet<Object>();
        boolean b1 = set.add(2018);
        boolean b2 = set.add("Hello");
        boolean b3 = set.add(2018);
        System.out.println(b1);//true
        System.out.println(b2);//true
        System.out.println(b3);//false
    }

輸出一下,結果是:

true
true
false

也就是說,(結合HashSet的add方法源碼)當add相同元素的時候,map.put(e, PRESENT) != null ,再來看一下一個map的例子:

public static void main(String[] args) {
        Map<Object, Object> map = new HashMap<Object, Object>();
        Object o1 = map.put(2018, 11111);
        Object o2 = map.put("Hello", "world");
        Object o3 = map.put(2018, 22222);
        System.out.println(o1);
        System.out.println(o2);
        System.out.println(o3);
    }

輸出:

null
null
11111

可以發現,當map存入相同的key的時候,返回值是上一個value,這就使得set在add相同元素的時候,map.put(e, PRESENT) != null,

導致set在執行add方法的時返回false,add失敗。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM