Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
5a2448b1
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
5a2448b1
编写于
6月 20, 2013
作者:
M
mduigou
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8017088: Map/HashMap.compute() incorrect with key mapping to null value
Reviewed-by: dl, dholmes, plevart
上级
db6fa7bf
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
102 addition
and
35 deletion
+102
-35
src/share/classes/java/util/HashMap.java
src/share/classes/java/util/HashMap.java
+18
-18
src/share/classes/java/util/Map.java
src/share/classes/java/util/Map.java
+30
-10
test/java/util/Map/Defaults.java
test/java/util/Map/Defaults.java
+54
-7
未找到文件。
src/share/classes/java/util/HashMap.java
浏览文件 @
5a2448b1
...
@@ -1749,25 +1749,25 @@ public class HashMap<K,V>
...
@@ -1749,25 +1749,25 @@ public class HashMap<K,V>
V
oldValue
=
pEntry
.
value
;
V
oldValue
=
pEntry
.
value
;
if
(
oldValue
!=
null
)
{
if
(
oldValue
!=
null
)
{
V
newValue
=
remappingFunction
.
apply
(
key
,
oldValue
);
V
newValue
=
remappingFunction
.
apply
(
key
,
oldValue
);
if
(
newValue
==
null
)
{
// remove mapping
if
(
newValue
==
null
)
{
// remove mapping
modCount
++;
modCount
++;
size
--;
size
--;
tb
.
deleteTreeNode
(
p
);
tb
.
deleteTreeNode
(
p
);
pEntry
.
recordRemoval
(
this
);
pEntry
.
recordRemoval
(
this
);
if
(
tb
.
root
==
null
||
tb
.
first
==
null
)
{
if
(
tb
.
root
==
null
||
tb
.
first
==
null
)
{
// assert tb.root == null && tb.first == null :
// assert tb.root == null && tb.first == null :
// "TreeBin.first and root should both be null";
// "TreeBin.first and root should both be null";
// TreeBin is now empty, we should blank this bin
// TreeBin is now empty, we should blank this bin
table
[
i
]
=
null
;
table
[
i
]
=
null
;
}
}
else
{
pEntry
.
value
=
newValue
;
pEntry
.
recordAccess
(
this
);
}
}
return
newValue
;
}
else
{
pEntry
.
value
=
newValue
;
pEntry
.
recordAccess
(
this
);
}
}
return
newValue
;
}
}
}
}
}
return
null
;
return
null
;
}
}
...
@@ -1779,7 +1779,7 @@ public class HashMap<K,V>
...
@@ -1779,7 +1779,7 @@ public class HashMap<K,V>
if
(
key
==
null
)
{
if
(
key
==
null
)
{
V
oldValue
=
nullKeyEntry
==
null
?
null
:
nullKeyEntry
.
value
;
V
oldValue
=
nullKeyEntry
==
null
?
null
:
nullKeyEntry
.
value
;
V
newValue
=
remappingFunction
.
apply
(
key
,
oldValue
);
V
newValue
=
remappingFunction
.
apply
(
key
,
oldValue
);
if
(
newValue
!=
oldValue
)
{
if
(
newValue
!=
oldValue
||
(
oldValue
==
null
&&
nullKeyEntry
!=
null
)
)
{
if
(
newValue
==
null
)
{
if
(
newValue
==
null
)
{
removeNullKey
();
removeNullKey
();
}
else
{
}
else
{
...
@@ -1803,7 +1803,7 @@ public class HashMap<K,V>
...
@@ -1803,7 +1803,7 @@ public class HashMap<K,V>
if
(
e
.
hash
==
hash
&&
Objects
.
equals
(
e
.
key
,
key
))
{
if
(
e
.
hash
==
hash
&&
Objects
.
equals
(
e
.
key
,
key
))
{
V
oldValue
=
e
.
value
;
V
oldValue
=
e
.
value
;
V
newValue
=
remappingFunction
.
apply
(
key
,
oldValue
);
V
newValue
=
remappingFunction
.
apply
(
key
,
oldValue
);
if
(
newValue
!=
oldValue
)
{
if
(
newValue
!=
oldValue
||
oldValue
==
null
)
{
if
(
newValue
==
null
)
{
if
(
newValue
==
null
)
{
modCount
++;
modCount
++;
size
--;
size
--;
...
@@ -1829,7 +1829,7 @@ public class HashMap<K,V>
...
@@ -1829,7 +1829,7 @@ public class HashMap<K,V>
TreeNode
p
=
tb
.
getTreeNode
(
hash
,
key
);
TreeNode
p
=
tb
.
getTreeNode
(
hash
,
key
);
V
oldValue
=
p
==
null
?
null
:
(
V
)
p
.
entry
.
value
;
V
oldValue
=
p
==
null
?
null
:
(
V
)
p
.
entry
.
value
;
V
newValue
=
remappingFunction
.
apply
(
key
,
oldValue
);
V
newValue
=
remappingFunction
.
apply
(
key
,
oldValue
);
if
(
newValue
!=
oldValue
)
{
if
(
newValue
!=
oldValue
||
(
oldValue
==
null
&&
p
!=
null
)
)
{
if
(
newValue
==
null
)
{
if
(
newValue
==
null
)
{
Entry
<
K
,
V
>
pEntry
=
(
Entry
<
K
,
V
>)
p
.
entry
;
Entry
<
K
,
V
>
pEntry
=
(
Entry
<
K
,
V
>)
p
.
entry
;
modCount
++;
modCount
++;
...
...
src/share/classes/java/util/Map.java
浏览文件 @
5a2448b1
...
@@ -640,7 +640,7 @@ public interface Map<K,V> {
...
@@ -640,7 +640,7 @@ public interface Map<K,V> {
* @param key key with which the specified value is to be associated
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or
* @return the previous value associated with the specified key, or
* {@code
1
} if there was no mapping for the key.
* {@code
null
} if there was no mapping for the key.
* (A {@code null} return can also indicate that the map
* (A {@code null} return can also indicate that the map
* previously associated {@code null} with the key,
* previously associated {@code null} with the key,
* if the implementation supports null values.)
* if the implementation supports null values.)
...
@@ -994,20 +994,40 @@ public interface Map<K,V> {
...
@@ -994,20 +994,40 @@ public interface Map<K,V> {
V
oldValue
=
get
(
key
);
V
oldValue
=
get
(
key
);
for
(;;)
{
for
(;;)
{
V
newValue
=
remappingFunction
.
apply
(
key
,
oldValue
);
V
newValue
=
remappingFunction
.
apply
(
key
,
oldValue
);
if
(
oldValue
!=
null
)
{
if
(
newValue
==
null
)
{
if
(
newValue
!=
null
)
{
// delete mapping
if
(
replace
(
key
,
oldValue
,
newValue
))
if
(
oldValue
!=
null
||
containsKey
(
key
))
{
return
newValue
;
// something to remove
}
else
if
(
remove
(
key
,
oldValue
))
{
if
(
remove
(
key
,
oldValue
))
{
// removed the old value as expected
return
null
;
}
// some other value replaced old value. try again.
oldValue
=
get
(
key
);
}
else
{
// nothing to do. Leave things as they were.
return
null
;
return
null
;
}
}
oldValue
=
get
(
key
);
}
else
{
}
else
{
if
(
newValue
!=
null
)
{
// add or replace old mapping
if
((
oldValue
=
putIfAbsent
(
key
,
newValue
))
==
null
)
if
(
oldValue
!=
null
)
{
// replace
if
(
replace
(
key
,
oldValue
,
newValue
))
{
// replaced as expected.
return
newValue
;
return
newValue
;
}
// some other value replaced old value. try again.
oldValue
=
get
(
key
);
}
else
{
}
else
{
return
null
;
// add (replace if oldValue was null)
if
((
oldValue
=
putIfAbsent
(
key
,
newValue
))
==
null
)
{
// replaced
return
newValue
;
}
// some other value replaced old value. try again.
}
}
}
}
}
}
...
...
test/java/util/Map/Defaults.java
浏览文件 @
5a2448b1
...
@@ -271,14 +271,21 @@ public class Defaults {
...
@@ -271,14 +271,21 @@ public class Defaults {
@Test
(
dataProvider
=
"Map<IntegerEnum,String> rw=true keys=withNull values=withNull"
)
@Test
(
dataProvider
=
"Map<IntegerEnum,String> rw=true keys=withNull values=withNull"
)
public
void
testComputeIfPresentNulls
(
String
description
,
Map
<
IntegerEnum
,
String
>
map
)
{
public
void
testComputeIfPresentNulls
(
String
description
,
Map
<
IntegerEnum
,
String
>
map
)
{
assertTrue
(
map
.
containsKey
(
null
));
assertTrue
(
map
.
containsKey
(
null
)
,
description
+
": null key absent"
);
assertNull
(
map
.
get
(
null
));
assertNull
(
map
.
get
(
null
)
,
description
+
": value not null"
);
assertSame
(
map
.
computeIfPresent
(
null
,
(
k
,
v
)
->
{
assertSame
(
map
.
computeIfPresent
(
null
,
(
k
,
v
)
->
{
fail
();
fail
(
description
+
": null value is not deemed present"
);
return
EXTRA_VALUE
;
return
EXTRA_VALUE
;
}),
null
,
description
);
}),
null
,
description
);
assertTrue
(
map
.
containsKey
(
null
));
assertTrue
(
map
.
containsKey
(
null
));
assertSame
(
map
.
get
(
null
),
null
,
description
);
assertNull
(
map
.
get
(
null
),
description
);
assertNull
(
map
.
remove
(
EXTRA_KEY
),
description
+
": unexpected mapping"
);
assertNull
(
map
.
put
(
EXTRA_KEY
,
null
),
description
+
": unexpected value"
);
assertSame
(
map
.
computeIfPresent
(
EXTRA_KEY
,
(
k
,
v
)
->
{
fail
(
description
+
": null value is not deemed present"
);
return
EXTRA_VALUE
;
}),
null
,
description
);
assertNull
(
map
.
get
(
EXTRA_KEY
),
description
+
": null mapping gone"
);
}
}
@Test
(
dataProvider
=
"Map<IntegerEnum,String> rw=true keys=all values=all"
)
@Test
(
dataProvider
=
"Map<IntegerEnum,String> rw=true keys=all values=all"
)
...
@@ -306,6 +313,12 @@ public class Defaults {
...
@@ -306,6 +313,12 @@ public class Defaults {
public
void
testComputeNulls
(
String
description
,
Map
<
IntegerEnum
,
String
>
map
)
{
public
void
testComputeNulls
(
String
description
,
Map
<
IntegerEnum
,
String
>
map
)
{
assertTrue
(
map
.
containsKey
(
null
),
"null key absent"
);
assertTrue
(
map
.
containsKey
(
null
),
"null key absent"
);
assertNull
(
map
.
get
(
null
),
"value not null"
);
assertNull
(
map
.
get
(
null
),
"value not null"
);
assertSame
(
map
.
compute
(
null
,
(
k
,
v
)
->
{
assertNull
(
k
);
assertNull
(
v
);
return
null
;
}),
null
,
description
);
assertFalse
(
map
.
containsKey
(
null
),
description
+
": null key present."
);
assertSame
(
map
.
compute
(
null
,
(
k
,
v
)
->
{
assertSame
(
map
.
compute
(
null
,
(
k
,
v
)
->
{
assertSame
(
k
,
null
);
assertSame
(
k
,
null
);
assertNull
(
v
);
assertNull
(
v
);
...
@@ -313,13 +326,47 @@ public class Defaults {
...
@@ -313,13 +326,47 @@ public class Defaults {
}),
EXTRA_VALUE
,
description
);
}),
EXTRA_VALUE
,
description
);
assertTrue
(
map
.
containsKey
(
null
));
assertTrue
(
map
.
containsKey
(
null
));
assertSame
(
map
.
get
(
null
),
EXTRA_VALUE
,
description
);
assertSame
(
map
.
get
(
null
),
EXTRA_VALUE
,
description
);
assertSame
(
map
.
remove
(
null
),
EXTRA_VALUE
,
"removed value not expected"
);
assertSame
(
map
.
remove
(
null
),
EXTRA_VALUE
,
description
+
": removed value not expected"
);
assertFalse
(
map
.
containsKey
(
null
),
"null key present"
);
// no mapping before and after
assertFalse
(
map
.
containsKey
(
null
),
description
+
": null key present"
);
assertSame
(
map
.
compute
(
null
,
(
k
,
v
)
->
{
assertSame
(
map
.
compute
(
null
,
(
k
,
v
)
->
{
assertSame
(
k
,
null
);
assertNull
(
k
);
assertNull
(
v
);
return
null
;
}),
null
,
description
+
": expected null result"
);
assertFalse
(
map
.
containsKey
(
null
),
description
+
": null key present"
);
// compute with map not containing value
assertNull
(
map
.
remove
(
EXTRA_KEY
),
description
+
": unexpected mapping"
);
assertFalse
(
map
.
containsKey
(
EXTRA_KEY
),
description
+
": key present"
);
assertSame
(
map
.
compute
(
EXTRA_KEY
,
(
k
,
v
)
->
{
assertSame
(
k
,
EXTRA_KEY
);
assertNull
(
v
);
return
null
;
}),
null
,
description
);
assertFalse
(
map
.
containsKey
(
EXTRA_KEY
),
description
+
": null key present"
);
// ensure removal.
assertNull
(
map
.
put
(
EXTRA_KEY
,
EXTRA_VALUE
));
assertSame
(
map
.
compute
(
EXTRA_KEY
,
(
k
,
v
)
->
{
assertSame
(
k
,
EXTRA_KEY
);
assertSame
(
v
,
EXTRA_VALUE
);
return
null
;
}),
null
,
description
+
": null resulted expected"
);
assertFalse
(
map
.
containsKey
(
EXTRA_KEY
),
description
+
": null key present"
);
// compute with map containing null value
assertNull
(
map
.
put
(
EXTRA_KEY
,
null
),
description
+
": unexpected value"
);
assertSame
(
map
.
compute
(
EXTRA_KEY
,
(
k
,
v
)
->
{
assertSame
(
k
,
EXTRA_KEY
);
assertNull
(
v
);
assertNull
(
v
);
return
null
;
return
null
;
}),
null
,
description
);
}),
null
,
description
);
assertFalse
(
map
.
containsKey
(
EXTRA_KEY
),
description
+
": null key present"
);
assertNull
(
map
.
put
(
EXTRA_KEY
,
null
),
description
+
": unexpected value"
);
assertSame
(
map
.
compute
(
EXTRA_KEY
,
(
k
,
v
)
->
{
assertSame
(
k
,
EXTRA_KEY
);
assertNull
(
v
);
return
EXTRA_VALUE
;
}),
EXTRA_VALUE
,
description
);
assertTrue
(
map
.
containsKey
(
EXTRA_KEY
),
"null key present"
);
}
}
@Test
(
dataProvider
=
"Map<IntegerEnum,String> rw=true keys=all values=all"
)
@Test
(
dataProvider
=
"Map<IntegerEnum,String> rw=true keys=all values=all"
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录