Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8071667

HashMap.computeIfAbsent() adds entry that HashMap.get() does not find.

    XMLWordPrintable

Details

    • b59
    • x86_64
    • windows_7
    • Verified

    Backports

      Description

        FULL PRODUCT VERSION :
        java version "1.8.0_31"
        Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
        Java HotSpot(TM) Client VM (build 25.31-b07, mixed mode, sharing)


        A DESCRIPTION OF THE PROBLEM :
        If the function supplied to computeIfAbsent adds items to the same HashTable on which the function is called from and the internal table is enlarged because of this, the new entry will be added to the wrong place in the Map's internal table making it inaccessible.

        Javadoc for Map.computeIfAbsent() is:

             * <pre> {@code
             * if (map.get(key) == null) {
             * V newValue = mappingFunction.apply(key);
             * if (newValue != null)
             * map.put(key, newValue);
             * }
             * }

        The implementation does not act this way when the internal table is enlarged.

        This was debugged using the source code for HashMap.


        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Compile are run the given test case.



        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The entry added to the Map will be accessible. So the assert should not fail.

        assert map.containsKey(KEY);
        ACTUAL -
        Entry added is inaccessible. Assertion fails.

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        import java.util.HashMap;
        import java.util.Map;


        public class HashMapTest {
        public static void main(String[] args) {
        final int LIMIT = 64;
        Map<String, String> map = new HashMap<>();
        final String KEY = "key";

        map.computeIfAbsent(KEY, k -> {
        for(int i=0; i<LIMIT; ++i)
        map.put(i+"", "junk");
        return "value";

        });

        System.out.println("map.contains = "+map.containsKey(KEY));
        assert map.containsKey(KEY);
        }
        }

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        Don't use computeIfAbsent() on HashMap. You can use the following static method workaround.

        public static <K, V> V computeIfAbsent(Map<K,V> map, K key, Function<? super K, ? extends V> mappingFunction) {
        if (map.containsKey(key))
        return map.get(key);
        else {
        V v = mappingFunction.apply(key);
        map.put(key, v);
        return v;
        }
        }

        Attachments

          Issue Links

            Activity

              People

                bchristi Brent Christian
                webbuggrp Webbug Group
                Votes:
                0 Vote for this issue
                Watchers:
                7 Start watching this issue

                Dates

                  Created:
                  Updated:
                  Resolved: