java - 如何从地图中删除所有空元素?

java - How to remove all null elements from a Map?

最简单的问题形式是我有一个集合,我想 delete/remove 其 value == null 的所有元素。我不想就地删除(我想得到新地图,这样我原来的地图就安全了)。

public Map<String, String> ADDITIONAL_QUERY = new HashMap<>();
this.ADDITIONAL_QUERY.put("deviceManufacturer", payload.getManufacturer());
this.ADDITIONAL_QUERY.put("deviceModel", payload.getModel());
this.ADDITIONAL_QUERY.put("source", payload.getSource());
this.ADDITIONAL_QUERY.put("adrIMEI", payload.getIMEI());
this.ADDITIONAL_QUERY.put("adrMEID", payload.getMEID());
this.ADDITIONAL_QUERY.put("adrUDID", payload.getUuid() == null ? null : payload.getUuid().toString());
this.ADDITIONAL_QUERY.put("adrID", payload.getAndroidId());
this.ADDITIONAL_QUERY.put("adrSERIAL", payload.getSerial());

我向 ADDITIONAL_QUERY 添加更多元素取决于我稍后调用的内容 API。

更多详情

我刚刚将我的 Retrofit 库升级到 2.0 版。我的大多数 API 中有 @FieldMap Map<String, String> additionalQuery(大约 100 API)。根据他们的文档,FieldMap、"Named key/value pairs for a form-encoded request. A null value for the map, as a key, or as a value is not allowed.",正如 java 文档中提到的那样(很有趣,他们在网络上的文档说你可以 https://square.github.io/retrofit/2.x/retrofit/index.html?retrofit2/http/class-use/FieldMap.html)。

由于 API 经常被调用,我正在寻找一种开销较小且速度当然快的方法。

您可以使用:

map.values().removeAll(Collections.singleton(null));

如果您有 Guava,您可以创建过滤视图以避免复制到新地图:

Map<String, String> filtered = Maps.filterValues(ADDITIONAL_QUERY, new Predicate<String>() {
    @Override
    public boolean apply(String value) {
        return value != null;
    }
});

因为你在 Java 8,你可以像这样缩短谓词:

Map<String, String> filtered = Maps.filterValues(ADDITIONAL_QUERY, Objects::nonNull);

你可以使用这个:

Map newMap = (HashMap) ADDITIONAL_QUERY.clone();;

newMap.values().remove(null);

可能的解决方案如下:

public <K, V> Map<K,V> removeNulls(Map<K,V> original) {
  return original.entrySet().stream().filter(e -> e.getValue() != null)
                 .collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
}

如果地图很大,那么你甚至可以使用 parallelStream() 而不是 stream()

这应该有效:

map.values().removeIf(Objects::isNull);