我正在处理在密钥和/或值中有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)));
我得到以下输出:
SomE => GreETing
HELLO => null
null => WOrLd
我需要转换地图,因此所有非空值都会转换为小写,如下所示:
some => greeting
hello => null
null => world
我正在尝试使用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)));
如果我注释掉最后两个映射条目,程序就会执行,因此当键或值为空时,Collectors.toMap
的工作方式一定存在问题。如何使用流API解决此问题?
答案 0 :(得分:12)
问题是toMap()
调用正在构建的基础Map实现merge()
函数,该函数不允许值为null
来自Map#merge
的javadoc(强调我的)
如果指定的键尚未与值关联或与null关联,则将其与给定的非null 值相关联。否则,将相关值替换为给定重映射函数的结果,或者如果结果为null则删除。
因此使用Collectors.toMap()
将无效。
你可以在没有流的情况下做到这一点:
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
);
}
答案 1 :(得分:9)
使用收集:
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);
Map<String, String> copy = Stream.of(headers)
.collect(HashMap::new,
(m, e) -> m.put(N.toLowerCase(e.getKey()), N.toLowerCase(e.getValue())));
在2月4日更新,或者:
Map<String, String> copy = EntryStream.of(headers)
.toMap(entry -> N.toLowerCase(entry.getKey()), entry -> N.toLowerCase(entry.getValue()));
答案 2 :(得分:2)
由于Collectors.toMap()
中存在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);
打印出来;
{null=world, some=greeting, hello=null, good=asdf}