我正在使用 Java 流对某些数据执行一些转换。我想忽略地图中包含空值的任何值。
例子:
HashMap<String, Object> vals = new HashMap<>();
vals.put("null", null);
vals.put("string1", "1 ");
Run Code Online (Sandbox Code Playgroud)
我试过使用过滤器:
Map<String, Object> nullMap = vals.entrySet().stream()
.filter(e -> e.getValue() != null)
.collect(Collectors.toMap(
e -> e.getKey().trim(),
e -> (e.getValue() instanceof String ? ((String) e.getValue()).trim() : e.getValue())))
Run Code Online (Sandbox Code Playgroud)
但是,返回的对象完全删除了空键/值对(在我的示例中为“空”-> 空)。如何.filter在 Java 流中的步骤之后的任何后续处理过程中保留键“null”并忽略它?
在上面的例子中,我想得到一个返回的 Map ,其中键和值对被修剪,并且在修剪步骤中空值被“忽略”。
该toMap收集不允许null值,所以你不能用它制作一个Map包含null值。
如果您的输入映射是可变的并且更改它是一个选项,您可以像这样简单地修剪值
HashMap<String, Object> vals = new HashMap<>();
vals.put("null", null);
vals.put("string1", "1 ");
vals.replaceAll((key,val) -> val instanceof String? ((String)val).trim(): val);
Run Code Online (Sandbox Code Playgroud)
如果修改源映射不是一种选择,或者您确实必须修剪键,则必须使用不同的收集器。您可以定义一个特别收集器,例如
HashMap<String, Object> result = vals.entrySet().stream()
.collect(HashMap::new, (m,e) -> m.put(e.getKey().trim(),
e.getValue() instanceof String? ((String)e.getValue()).trim(): e.getValue()),
Map::putAll);
Run Code Online (Sandbox Code Playgroud)
为了更好的可读性,即避免重复相同的表达式,我们可以使用块 lambda 语法和一个局部变量,如
HashMap<String, Object> result = vals.entrySet().stream()
.collect(
HashMap::new,
(m,e) -> {
Object value = e.getValue();
m.put(e.getKey().trim(), value instanceof String? ((String)value).trim(): value);
}, Map::putAll);
Run Code Online (Sandbox Code Playgroud)
请注意,当应用trim()到键时,即使键在原始映射中是唯一的,例如当具有" key1"和时,它们也可能会发生冲突"key1 "。该toMap收藏家就扔在这样的情况下,而上述矛盾的映射会简单地覆盖一个没有警告创建的临时收集器。