ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ConcurrentSkipListMap.java
(Generate patch)

Comparing jsr166/src/main/java/util/concurrent/ConcurrentSkipListMap.java (file contents):
Revision 1.108 by jsr166, Sun Mar 17 15:34:21 2013 UTC vs.
Revision 1.109 by dl, Mon Mar 18 12:40:30 2013 UTC

# Line 10 | Line 10 | import java.util.stream.Stream;
10   import java.util.Spliterator;
11   import java.util.stream.Streams;
12   import java.util.function.Consumer;
13 + import java.util.function.Function;
14 + import java.util.function.BiFunction;
15  
16   /**
17   * A scalable concurrent {@link ConcurrentNavigableMap} implementation.
# Line 1842 | Line 1844 | public class ConcurrentSkipListMap<K,V>
1844      }
1845  
1846      /**
1847 +     * Returns the value to which the specified key is mapped,
1848 +     * or the given defaultValue if this map contains no mapping for the key.
1849 +     *
1850 +     * @param key the key
1851 +     * @param defaultValue the value to return if this map contains
1852 +     * no mapping for the given key
1853 +     * @return the mapping for the key, if present; else the defaultValue
1854 +     * @throws NullPointerException if the specified key is null
1855 +     * @since 1.8
1856 +     */
1857 +    public V getOrDefault(Object key, V defaultValue) {
1858 +        V v;
1859 +        return (v = get(key)) == null ? defaultValue : v;
1860 +    }
1861 +
1862 +    /**
1863       * Associates the specified value with the specified key in this map.
1864       * If the map previously contained a mapping for the key, the old
1865       * value is replaced.
# Line 1941 | Line 1959 | public class ConcurrentSkipListMap<K,V>
1959          initialize();
1960      }
1961  
1962 +    /**
1963 +     * If the specified key is not already associated with a value,
1964 +     * attempts to compute its value using the given mapping function
1965 +     * and enters it into this map unless {@code null}.  The function
1966 +     * is <em>NOT</em> guaranteed to be applied once atomically only
1967 +     * if the value is not present.
1968 +     *
1969 +     * @param key key with which the specified value is to be associated
1970 +     * @param mappingFunction the function to compute a value
1971 +     * @return the current (existing or computed) value associated with
1972 +     *         the specified key, or null if the computed value is null
1973 +     * @throws NullPointerException if the specified key is null
1974 +     *         or the mappingFunction is null
1975 +     * @since 1.8
1976 +     */
1977 +    public V computeIfAbsent(K key,
1978 +                             Function<? super K, ? extends V> mappingFunction) {
1979 +        if (key == null || mappingFunction == null)
1980 +            throw new NullPointerException();
1981 +        Comparator<? super K> cmp;
1982 +        V v, p, r;
1983 +        if ((cmp = comparator) == null) {
1984 +            if ((v = doGet(key)) == null &&
1985 +                (r = mappingFunction.apply(key)) != null)
1986 +                v = (p = doPut(key, r, true)) == null ? r : p;
1987 +        }
1988 +        else {
1989 +            if ((v = doGetCmp(cmp, key)) == null &&
1990 +                (r = mappingFunction.apply(key)) != null)
1991 +                v = (p = doPutCmp(cmp, key, r, true)) == null ? r : p;
1992 +        }
1993 +        return v;
1994 +    }
1995 +
1996 +    /**
1997 +     * If the value for the specified key is present, attempts to
1998 +     * compute a new mapping given the key and its current mapped
1999 +     * value. The function is <em>NOT</em> guaranteed to be applied
2000 +     * once atomically.
2001 +     *
2002 +     * @param key key with which the specified value is to be associated
2003 +     * @param remappingFunction the function to compute a value
2004 +     * @return the new value associated with the specified key, or null if none
2005 +     * @throws NullPointerException if the specified key is null
2006 +     *         or the remappingFunction is null
2007 +     * @since 1.8
2008 +     */
2009 +    public V computeIfPresent(K key,
2010 +                              BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
2011 +        if (key == null || remappingFunction == null)
2012 +            throw new NullPointerException();
2013 +        Comparator<? super K> cmp;
2014 +        if ((cmp = comparator) == null) {
2015 +            Node<K,V> n; Object v;
2016 +            @SuppressWarnings("unchecked") Comparable<? super K> k =
2017 +                (Comparable<? super K>) key;
2018 +            while ((n = findNode(k)) != null) {
2019 +                if ((v = n.value) != null) {
2020 +                    @SuppressWarnings("unchecked") V vv = (V) v;
2021 +                    V r = remappingFunction.apply(key, vv);
2022 +                    if (r != null) {
2023 +                        if (n.casValue(vv, r))
2024 +                            return r;
2025 +                    }
2026 +                    else if (doRemove(k, vv) != null)
2027 +                        break;
2028 +                }
2029 +            }
2030 +        }
2031 +        else {
2032 +            Node<K,V> n; Object v;
2033 +            while ((n = findNodeCmp(cmp, key)) != null) {
2034 +                if ((v = n.value) != null) {
2035 +                    @SuppressWarnings("unchecked") V vv = (V) v;
2036 +                    V r = remappingFunction.apply(key, vv);
2037 +                    if (r != null) {
2038 +                        if (n.casValue(vv, r))
2039 +                            return r;
2040 +                    }
2041 +                    else if (doRemoveCmp(cmp, key, vv) != null)
2042 +                        break;
2043 +                }
2044 +            }
2045 +        }
2046 +        return null;
2047 +    }
2048 +
2049 +    /**
2050 +     * Attempts to compute a mapping for the specified key and its
2051 +     * current mapped value (or {@code null} if there is no current
2052 +     * mapping). The function is <em>NOT</em> guaranteed to be applied
2053 +     * once atomically.
2054 +     *
2055 +     * @param key key with which the specified value is to be associated
2056 +     * @param remappingFunction the function to compute a value
2057 +     * @return the new value associated with the specified key, or null if none
2058 +     * @throws NullPointerException if the specified key is null
2059 +     *         or the remappingFunction is null
2060 +     * @since 1.8
2061 +     */
2062 +    public V compute(K key,
2063 +                     BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
2064 +        if (key == null || remappingFunction == null)
2065 +            throw new NullPointerException();
2066 +        Comparator<? super K> cmp;
2067 +        if ((cmp = comparator) == null) {
2068 +            @SuppressWarnings("unchecked") Comparable<? super K> k =
2069 +                (Comparable<? super K>) key;
2070 +            for (;;) {
2071 +                Node<K,V> n; Object v; V r;
2072 +                if ((n = findNode(k)) == null) {
2073 +                    if ((r = remappingFunction.apply(key, null)) == null)
2074 +                        break;
2075 +                    if (doPut(key, r, false) == null)
2076 +                        return r;
2077 +                }
2078 +                else if ((v = n.value) != null) {
2079 +                    @SuppressWarnings("unchecked") V vv = (V) v;
2080 +                    if ((r = remappingFunction.apply(key, vv)) != null) {
2081 +                        if (n.casValue(vv, r))
2082 +                            return r;
2083 +                    }
2084 +                    else if (doRemove(k, vv) != null)
2085 +                        break;
2086 +                }
2087 +            }
2088 +        }
2089 +        else {
2090 +            for (;;) {
2091 +                Node<K,V> n; Object v; V r;
2092 +                if ((n = findNodeCmp(cmp, key)) == null) {
2093 +                    if ((r = remappingFunction.apply(key, null)) == null)
2094 +                        break;
2095 +                    if (doPutCmp(cmp, key, r, false) == null)
2096 +                        return r;
2097 +                }
2098 +                else if ((v = n.value) != null) {
2099 +                    @SuppressWarnings("unchecked") V vv = (V) v;
2100 +                    if ((r = remappingFunction.apply(key, vv)) != null) {
2101 +                        if (n.casValue(vv, r))
2102 +                            return r;
2103 +                    }
2104 +                    else if (doRemoveCmp(cmp, key, vv) != null)
2105 +                        break;
2106 +                }
2107 +            }
2108 +        }
2109 +        return null;
2110 +    }
2111 +
2112 +    /**
2113 +     * If the specified key is not already associated with a value,
2114 +     * associates it with the given value.  Otherwise, replaces the
2115 +     * value with the results of the given remapping function, or
2116 +     * removes if {@code null}. The function is <em>NOT</em>
2117 +     * guaranteed to be applied once atomically.
2118 +     *
2119 +     * @param key key with which the specified value is to be associated
2120 +     * @param value the value to use if absent
2121 +     * @param remappingFunction the function to recompute a value if present
2122 +     * @return the new value associated with the specified key, or null if none
2123 +     * @throws NullPointerException if the specified key or value is null
2124 +     *         or the remappingFunction is null
2125 +     * @since 1.8
2126 +     */
2127 +    public V merge(K key, V value,
2128 +                   BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
2129 +        if (key == null || value == null || remappingFunction == null)
2130 +            throw new NullPointerException();
2131 +        Comparator<? super K> cmp;
2132 +        if ((cmp = comparator) == null) {
2133 +            @SuppressWarnings("unchecked") Comparable<? super K> k =
2134 +                (Comparable<? super K>) key;
2135 +            for (;;) {
2136 +                Node<K,V> n; Object v; V r;
2137 +                if ((n = findNode(k)) == null) {
2138 +                    if (doPut(key, value, false) == null)
2139 +                        return value;
2140 +                }
2141 +                else if ((v = n.value) != null) {
2142 +                    @SuppressWarnings("unchecked") V vv = (V) v;
2143 +                    if ((r = remappingFunction.apply(vv, value)) != null) {
2144 +                        if (n.casValue(vv, r))
2145 +                            return r;
2146 +                    }
2147 +                    else if (doRemove(k, vv) != null)
2148 +                        return null;
2149 +                }
2150 +            }
2151 +        }
2152 +        else {
2153 +            for (;;) {
2154 +                Node<K,V> n; Object v; V r;
2155 +                if ((n = findNodeCmp(cmp, key)) == null) {
2156 +                    if (doPutCmp(cmp, key, value, false) == null)
2157 +                        return value;
2158 +                }
2159 +                else if ((v = n.value) != null) {
2160 +                    @SuppressWarnings("unchecked") V vv = (V) v;
2161 +                    if ((r = remappingFunction.apply(vv, value)) != null) {
2162 +                        if (n.casValue(vv, r))
2163 +                            return r;
2164 +                    }
2165 +                    else if (doRemoveCmp(cmp, key, vv) != null)
2166 +                        return null;
2167 +                }
2168 +            }
2169 +        }
2170 +    }
2171 +
2172      /* ---------------- View methods -------------- */
2173  
2174      /*
# Line 3544 | Line 3772 | public class ConcurrentSkipListMap<K,V>
3772          public NavigableSet<K> descendingSet() {
3773              return new KeySet<K>(m.descendingMap());
3774          }
3547
3775          public Spliterator<K> spliterator() {
3776              return m.keySpliterator();
3777          }
3551
3778      }
3779  
3780      /**
# Line 3582 | Line 3808 | public class ConcurrentSkipListMap<K,V>
3808                  HeadIndex<K,V> h; Node<K,V> p;
3809                  Node<K,V> b = (h = m.head).node;
3810                  if ((p = b.next) == null || p.value != null) {
3811 <                    this.est = ((p == null) ? 0 :
3586 <                                (p.next == null) ? 1 : Integer.MAX_VALUE);
3811 >                    this.est = (p == null) ? 0 : Integer.MAX_VALUE;
3812                      this.current = p;
3813                      this.row = h;
3814                      break;
# Line 3643 | Line 3868 | public class ConcurrentSkipListMap<K,V>
3868              if ((e = current) != null) {
3869                  for (Index<K,V> q = row; q != null; q = row = q.down) {
3870                      Index<K,V> s; Node<K,V> n; K sk;
3646                    est -= est >>> 2;
3871                      if ((s = q.right) != null) {
3872                          for (;;) {
3873                              Node<K,V> b = s.node;
# Line 3658 | Line 3882 | public class ConcurrentSkipListMap<K,V>
3882                              current = n;
3883                              Index<K,V> r = q.down;
3884                              row = (s.right != null) ? s : s.down;
3885 +                            est -= est >>> 2;
3886                              return new KeySpliterator<K,V>(cmp, r, e, sk, est);
3887                          }
3888                      }
# Line 3732 | Line 3957 | public class ConcurrentSkipListMap<K,V>
3957              if ((e = current) != null) {
3958                  for (Index<K,V> q = row; q != null; q = row = q.down) {
3959                      Index<K,V> s; Node<K,V> n; K sk;
3735                    est -= est >>> 2;
3960                      if ((s = q.right) != null) {
3961                          for (;;) {
3962                              Node<K,V> b = s.node;
# Line 3747 | Line 3971 | public class ConcurrentSkipListMap<K,V>
3971                              current = n;
3972                              Index<K,V> r = q.down;
3973                              row = (s.right != null) ? s : s.down;
3974 +                            est -= est >>> 2;
3975                              return new ValueSpliterator<K,V>(cmp, r, e, sk, est);
3976                          }
3977                      }
# Line 3819 | Line 4044 | public class ConcurrentSkipListMap<K,V>
4044              if ((e = current) != null) {
4045                  for (Index<K,V> q = row; q != null; q = row = q.down) {
4046                      Index<K,V> s; Node<K,V> n; K sk;
3822                    est -= est >>> 2;
4047                      if ((s = q.right) != null) {
4048                          for (;;) {
4049                              Node<K,V> b = s.node;
# Line 3835 | Line 4059 | public class ConcurrentSkipListMap<K,V>
4059                              current = n;
4060                              Index<K,V> r = q.down;
4061                              row = (s.right != null) ? s : s.down;
4062 +                            est -= est >>> 2;
4063                              return new EntrySpliterator<K,V>(cmp, r, e, sk, est);
4064                          }
4065                      }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines