📜  Java中Set/HashSet的内部工作

📅  最后修改于: 2022-05-13 01:55:44.288000             🧑  作者: Mango

Java中Set/HashSet的内部工作

正如我们所知,集合是定义明确的不同对象的集合。集合的每个成员称为集合的元素。所以换句话说,我们可以说一个集合永远不会包含重复的元素。但是在Java Set 接口中实现的类如 HashSet、LinkedHashSet、TreeSet 等如何实现这种唯一性。在这篇文章中,我们将讨论这种独特性背后隐藏的真相。

HashSet 如何在Java内部工作?

Set/HashSet 如何在 Java 内部工作
我们将通过一个示例来理解这一点。让我们看看以下程序的输出,该程序尝试在 HashSet 中添加重复元素。

// Java program to demonstrate
// internal working of HashSet
  
import java.util.HashSet;
  
class Test
{    
    public static void main(String args[]) 
    {
        // creating a HashSet
        HashSet hs = new HashSet();
          
        // adding elements to hashset
        // using add() method
        boolean b1 = hs.add("Geeks");
        boolean b2 = hs.add("GeeksforGeeks");
          
        // adding duplicate element
        boolean b3 = hs.add("Geeks");
          
        // printing b1, b2, b3
        System.out.println("b1 = "+b1);
        System.out.println("b2 = "+b2);
        System.out.println("b3 = "+b3);
          
        // printing all elements of hashset
        System.out.println(hs);
              
    }
}

输出:

b1 = true
b2 = true
b3 = false
[GeeksforGeeks, Geeks]

现在从输出中可以清楚地看出,当我们尝试使用add()方法将重复元素添加到集合中时,它会返回false ,并且元素不会添加到哈希集中,因为它已经存在。现在问题来了, add()方法如何检查集合是否已经包含指定的元素。如果我们仔细看看 HashSet 类中的add()方法和默认构造函数,就会更加清楚。

// predefined HashSet class
public class HashSet
{
    // A HashMap object 
    private transient HashMap map;

    // A Dummy value(PRESENT) to associate with an Object in the Map
    private static final Object PRESENT = new Object();
    
    // default constructor of HashSet class
    // It creates a HashMap by calling 
    // default constructor of HashMap class
    public HashSet() {
        map = new HashMap<>();
    }

    // add method 
    // it calls put() method on map object
    // and then compares it's return value with null
    public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
 
    // Other methods in Hash Set
}

现在你可以看到,每当我们创建一个 HashSet 时,它都会在内部创建一个 HashMap,如果我们使用add()方法将一个元素插入到这个 HashSet 中,它实际上会在内部创建的 HashMap 对象上调用put()方法,其中的元素指定为它是关键和常量对象,称为“PRESENT” ,因为它的值。所以我们可以说Set 通过 HashMap 在内部实现唯一性。现在整个故事都围绕着 HashMap 和put()方法如何在内部工作。

正如我们所知,在 HashMap 中每个键都是唯一的,当我们调用put(Key, Value)方法时,它会返回与键关联的先前值,如果键没有映射,则返回null 。所以在add()方法中,我们检查 map.put(key, value) 方法的返回值是否为值。

  1. 如果 map.put(key, value) 返回null ,则语句“map.put(e, PRESENT) == null”将返回true并将元素添加到 HashSet(internally HashMap)。
  2. 如果 map.put(key, value) 返回键的旧值,则语句“map.put(e, PRESENT) == null”将返回false ,并且元素不会添加到 HashSet(内部 HashMap)中。

由于 LinkedHashSet 扩展了 HashSet,所以它在内部使用 super() 调用 HashSet 的构造函数。类似地,在内部创建 TreeSet 类的对象会创建 Navigable Map 的对象作为支持地图。

相关文章: HashMap 如何在Java内部工作。