WeakHashMap WeakHashMap weakMap weakMap weakMap weakMap weakMap weakMap What are the applicable scenarios of WeakHashMap and what should be paid attention to when using it? How do weak and strong references affect the Java GC differently? This article will give a clear and concise introduction.

General introduction

At the end of the Java Collections Framework series, I’m going to introduce a special member: WeakHashMap, which, as its name suggests, is some kind of Map. It is special because entries in a WeakHashMap may be automatically deleted by GC, even if the programmer does not call the remove() or clear() methods.

More intuitively, when using WeakHashMap, even if no element is added or deleted as shown, the following situation may occur:

  • Call twicesize()Methods return different values;
  • Two callsisEmpty()Method, returns the first timefalse, return the second timetrue;
  • Two callscontainsKey()Method, returns the first timetrue, return the second timefalse“Even though it was the same onekey;
  • Two callsget()Method that returns one the first timevalue, return the second timenullEven though you’re using the same object twice.

Do you think users will go crazy with such a bizarre phenomenon? This feature of the WeekHashMap is particularly useful for scenarios that require caching. In the cache scenario, all objects cannot be cached because memory is limited. Object cache hits can improve system efficiency, but cache misses also don’t cause errors because they can be computed back.

To understand how the WeekHashMap works, you need to introduce another concept: WeakReference. We all know that memory in Java is managed automatically by GC, which determines which objects can be reclaimed during application execution and frees memory when appropriate. The GC determines whether an object is recyclable based on whether there is a valid reference to the object. If there is no valid reference to the object (which basically means there is no way to access it), then the object is recyclable. Valid references do not include weak references. That is, although weak references can be used to access objects, weak references are not taken into account for garbage collection, and only objects referred to by weak references are still collected by GC.

WeakHashMap internally manages entries through weak references. What does the property of weak references mean to WeakHashMap? Placing a pair of keys and values in a WeakHashMap does not prevent the key value from being collected by GC unless there is a strong reference to the key outside of a WeakHashMap.

The concepts of strong references and weak references will be discussed later, but it is enough to know that Java references are categorized and that different types of references have different effects on GC.

The specific implementation

The storage structure of WeakHashMap is similar to that of HashMap. Readers can refer to the previous paragraphs and will not repeat them here.

The blogger will explain the management of strong and weak references separately.

Weak HashSet?

If you’ve read the previous articles on maps and sets, you might be wondering: If there is a WeekHashMap, is there a WeekHashSet? The answer is no :(. But Java Collections utility class solution is given, and the Collections. NewSetFromMap (Map < E, Boolean > Map) method, any Map can be packaged into a Set. You can quickly get an Weak HashSet as follows:

// Wrap WeakHashMap as a Set
Set<Object> weakHashSet = Collections.newSetFromMap(
        new WeakHashMap<Object, Boolean>());
Copy the code

As you might expect, the newSetFromMap() method simply wraps the Map passed in:

/ / Collections. NewSetFromMap () is used to any Map packaged as a Set
public static <E> Set<E> newSetFromMap(Map<E, Boolean> map) {
    return new SetFromMap<>(map);
}

private static class SetFromMap<E> extends AbstractSet<E>
    implements Set<E>, Serializable
{
    private final Map<E, Boolean> m;  // The backing map
    private transient Set<E> s;       // Its keySet
    SetFromMap(Map<E, Boolean> map) {
        if(! map.isEmpty())throw new IllegalArgumentException("Map is non-empty");
        m = map;
        s = map.keySet();
    }
    public void clear(a)               {        m.clear(); }
    public int size(a)                 { return m.size(); }
    public boolean isEmpty(a)          { return m.isEmpty(); }
    public boolean contains(Object o) { return m.containsKey(o); }
    public boolean remove(Object o)   { returnm.remove(o) ! =null; }
    public boolean add(E e) { return m.put(e, Boolean.TRUE) == null; }
    public Iterator<E> iterator(a)     { return s.iterator(); }
    public Object[] toArray()         { return s.toArray(); }
    public <T> T[] toArray(T[] a)     { return s.toArray(a); }
    public String toString(a)          { return s.toString(); }
    public int hashCode(a)             { return s.hashCode(); }
    public boolean equals(Object o)   { return o == this || s.equals(o); }
    public boolean containsAll(Collection
        c) {returns.containsAll(c); }public boolean removeAll(Collection
        c)   {returns.removeAll(c); }public boolean retainAll(Collection
        c)   {returns.retainAll(c); }// addAll is the only inherited implementation. }Copy the code

conclusion

This is the end of the Java Collections Framework Internals series. I hope these short posts will help you build a basic understanding of the Java Container Framework. This is where you can return to the table of contents for this article series.

The blogger would be very happy if he could help you at least a little! If there are any flaws and fallacies in the blog, I welcome you to correct them.

GitHub address for this article