5
import java.util.HashMap;
import java.util.HashSet;

public class ComputeIfAbsentWithHashSetNew {
    public static void main(String[] args) {
        var map = new HashMap<Integer, HashSet<Integer>>();
        var data = new int[][]{{305589003, 4136}, {305589004, 4139}};
        for (var entry : data) {
            int x = entry[0];
            int y = entry[1];
//            map.computeIfAbsent(x, _x -> new HashSet<>()).add(y); // ----- line 1
            var k = map.computeIfAbsent(x, HashSet::new);           // ----- line 2
            k.add(y);
        }
    }
}

Above code throws at jdk 17、 18、 19:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at java.base/java.util.HashMap.resize(HashMap.java:702)
    at java.base/java.util.HashMap.putVal(HashMap.java:627)
    at java.base/java.util.HashMap.put(HashMap.java:610)
    at java.base/java.util.HashSet.add(HashSet.java:221)
    at _explore.ComputeIfAbsentWithHashSetNew.main(ComputeIfAbsentWithHashSetNew.java:15)

When debug, I see the newCap in Hashmap::resize() is very large, I don't know why. I thought both the lines do same thing previously.

When I replace line 2 with line 1 in code, it runs successfully.

2
  • 3
    "When I replace line 2 with line 1 in code, it runs successfully." because they do completely different things. One creates an HashSet with default capacity, the other creates an HashSet with initial capacity x, which may very well be 305589003, which is rather big. Commented Jan 20, 2023 at 7:37
  • 1
    computeIfAbsent calls the 2nd parameter (a Function) with the key as argument, in this case 305589003; the passed function HashSet::new is the HashSet(int initialCapacity) - as commented above, 305589003 as capacity is too big to be stored in the available memory (line 1 should be k -> new HashSet<>(k) to be the same as line 2, both wrong) Commented Jan 20, 2023 at 7:45

1 Answer 1

5

HashSet::new is a method reference pointing to new HashSet(initialCapacity). See the java-doc of HashSet.

So, it creates a bigger HashSets than you expect, because it takes your x variable as parameter.

Sign up to request clarification or add additional context in comments.

1 Comment

a detail: HashSet::new is not a lambda but just a method reference (according JLS 15.27. Lambda Expressions)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.