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. |
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. |
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 |
|
/* |
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 |
|
/** |
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; |
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; |
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 |
|
} |
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; |
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 |
|
} |
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; |
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 |
|
} |