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);
最简单的问题形式是我有一个集合,我想 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);