使用 Java 8 流转换带有空值的 Map
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42546950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Use Java 8 streams to transform a Map with nulls
提问by Web User
I am dealing with a Map<String,String>
that has null
entries in the key and/or value:
我正在处理在键和/或值Map<String,String>
中有null
条目的一个:
Map<String, String> headers = new HashMap<>();
headers.put("SomE", "GreETing");
headers.put("HELLO", null);
headers.put(null, "WOrLd");
headers.keySet().stream().forEach(k -> System.out.println(k + " => " + copy.get(k)));
I get the following output:
我得到以下输出:
SomE => GreETing
HELLO => null
null => WOrLd
I need to transform the map, so all the non-null values are converted to lowercase, like so:
我需要转换地图,因此所有非空值都转换为小写,如下所示:
some => greeting
hello => null
null => world
I am trying to use Java 8 streams API, but the following code is throwing NullPointerException
:
我正在尝试使用 Java 8 流 API,但以下代码正在抛出NullPointerException
:
Map<String,String> copy
= headers.entrySet()
.stream()
.collect(
Collectors.toMap(
it -> it.getKey() != null ? it.getKey().toLowerCase() : null,
it -> it.getValue() != null ? it.getValue().toLowerCase() : null));
copy.keySet().stream().forEach(k -> System.out.println(k + " => " + copy.get(k)));
If I comment out the last two map entries, the program executes, so there must be an issue with how Collectors.toMap
works when keys or values are null. How do I use the streams API to work around this?
如果我注释掉最后两个映射条目,程序就会执行,所以Collectors.toMap
当键或值为空时,程序的工作方式一定存在问题。我如何使用流 API 来解决这个问题?
回答by dkatzel
The problem is toMap()
invokes the underlying Map implementation being built's merge()
function which does not allow values to be null
问题是toMap()
调用正在构建的底层 Map 实现的merge()
函数,该函数不允许值为 null
from the javadoc for Map#merge
(emphasis mine)
来自 javadoc for Map#merge
(强调我的)
If the specified key is not already associated with a value or is associated with null, associates it with the given non-nullvalue. Otherwise, replaces the associated value with the results of the given remapping function, or removes if the result is null.
如果指定的键尚未与值相关联或与空值相关联,则将其与给定的非空值相关联。否则,用给定的重映射函数的结果替换关联的值,如果结果为空则删除。
So using Collectors.toMap()
will not work.
所以使用是Collectors.toMap()
行不通的。
You can do this without stream just fine:
你可以在没有流的情况下做到这一点:
Map<String,String> copy = new HashMap<>();
for(Entry<String, String> entry : headers.entrySet()){
copy.put(entry.getKey() !=null ? entry.getKey().toLowerCase() : null,
entry.getValue() !=null ? entry.getValue().toLowerCase() : null
);
}
回答by user_3380739
Use Collect:
使用收集:
final Function<String, String> fn= str -> str == null ? null : str.toLowerCase();
Map<String, String> copy = headers.entrySet().stream()
.collect(HashMap::new,
(m, e) -> m.put(fn.apply(e.getKey()), fn.apply(e.getValue())),
Map::putAll);
Or with AbacusUtil
或者使用AbacusUtil
Map<String, String> copy = Stream.of(headers)
.collect(HashMap::new,
(m, e) -> m.put(N.toLowerCase(e.getKey()), N.toLowerCase(e.getValue())));
updated on 2/4, Or:
2/4 更新,或:
Map<String, String> copy = EntryStream.of(headers)
.toMap(entry -> N.toLowerCase(entry.getKey()), entry -> N.toLowerCase(entry.getValue()));
回答by bur?quete
You cannot use Collectors.toMap()
without getting a NPE since you have a null
value
present in your map
, as explained by @dkatzel already, but I still wanted to use Stream API
;
不能使用Collectors.toMap()
没有得到一个NPE,因为你有null
value
你的存在map
,如@dkatzel已经解释过,但我还是想用Stream API
;
Map<String, String> headers = new HashMap<>();
headers.put("good", "AsDf");
headers.put("SomE", "GreETing");
headers.put("HELLO", null);
headers.put(null, "WOrLd");
new HashSet<>(headers.entrySet()).stream()
.peek(entry -> entry.setValue(Objects.isNull(entry.getValue()) ? null : entry.getValue().toLowerCase()))
.filter(entry -> !Objects.isNull(entry.getKey()) && !entry.getKey().equals(entry.getKey().toLowerCase()))
.forEach(entry -> {
headers.put(entry.getKey().toLowerCase(), entry.getValue());
headers.remove(entry.getKey());
});
System.out.println(headers);
Prints out;
打印出来;
{null=world, some=greeting, hello=null, good=asdf}