Java中Set/HashSet的内部工作
正如我们所知,集合是定义明确的不同对象的集合。集合的每个成员称为集合的元素。所以换句话说,我们可以说一个集合永远不会包含重复的元素。但是在Java Set 接口中实现的类如 HashSet、LinkedHashSet、TreeSet 等如何实现这种唯一性。在这篇文章中,我们将讨论这种独特性背后隐藏的真相。
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) 方法的返回值是否为空值。
- 如果 map.put(key, value) 返回null ,则语句“map.put(e, PRESENT) == null”将返回true并将元素添加到 HashSet(internally HashMap)。
- 如果 map.put(key, value) 返回键的旧值,则语句“map.put(e, PRESENT) == null”将返回false ,并且元素不会添加到 HashSet(内部 HashMap)中。
由于 LinkedHashSet 扩展了 HashSet,所以它在内部使用 super() 调用 HashSet 的构造函数。类似地,在内部创建 TreeSet 类的对象会创建 Navigable Map 的对象作为支持地图。
相关文章: HashMap 如何在Java内部工作。