在 Java 7 或更低版本中,HOWTO 使用在地图中找到的 key/value 过滤地图对象列表
In Java 7 or below, HOWTO filter a list of map objects using key/value found in the map
我有一个地图对象列表。这些地图对象有 properties/keys like id, condition_1, condition_2 等。示例地图看起来像这样,
List<Map<String, Object>> allItems = Lists.newArrayList();
Map<String, Object> paramsMap = Maps.newHashMap();
paramsMap.put("id", "a");
paramsMap.put("condition_1", false);
paramsMap.put("condition_2", true);
paramsMap.put("condition_3", false);
allItems.add(paramsMap);
因此,我需要过滤 allItems
对象,使其仅包含具有 condition_1 = true
和 condition_2 = false
等的地图对象。
我考虑过使用 apache commons CollectionUtils.filter 但这似乎并不能解决我的问题,因为我无法将映射条目指定为过滤条件。
我也不反对使用 Google 番石榴,但我找不到好的解决方案。
基本上,我试图模仿优秀的 JavaScript 库 underscore.js 中的 _.where
功能。
在 Java 8 中你可以使用流:
allItems.stream()
.filter(map->
(map.get("condition_1")==true)&&(map.get("condition_2")==false))
.forEach(System.out::println); //Example output
一个 Guava 解决方案:
Iterables.filter(allItems, new Predicate<Map<String, Object>>() {
@Override public boolean apply(Map<String, Object> map) {
return Boolean.TRUE.equals(map.get("condition_1"))
&& Boolean.FALSE.equals(map.get("condition_2"));
}
});
我认为您将不得不长期这样做。不幸的是 Java 映射不是 Iterable 类型,这意味着大多数常见的库没有针对它们的过滤函数。尝试这样的事情(我相信字符串在 java 中隐式为真,以防您担心您的第一个键值对):
```
boolean result = true;
boolean test = true;
List<Map<String, Object> resultList;
for(Map<String, Object> map : allitems) {
for(String key : map.keySet()) {
result = result && test && map.get(key);
test = !test;
}
if(result) {
resultList.add(map);
}
}
return resultList;
```
另一种可能性是将您的地图变成 KeyValue
s 的列表并使用 apache 映射和列表函数。最有可能的是,当您使用 java 7 时,您不会得到那个漂亮的衬垫。希望这对您有所帮助。
我认为最好的解决方案是实际执行与 Kotlin 在方法 Map<K, V>.filter
中所做的相同的操作。
让我们创建谓词:
public interface Predicate<T> {
boolean apply(T t);
}
Predicate 是一个对 functional-like 编程有用的接口。方法在满足条件时应用 returns true。
然后,像 CollectionUtils
一样创建 class 并在其中放置一个静态方法:
public static <K, V> Map<K, V> filter(
@NonNull Map<K, V> collection,
@NonNull Predicate<Map.Entry<K, V>> predicate
) {
Map<K, V> result = new HashMap<>();
for (Map.Entry<K, V> entry : collection.entrySet()) {
if (predicate.apply(entry) {
result.put(entry.getKey(), entry.getValue();
}
}
return result;
}
这样我们就可以按照以下方式使用这个方法:
Map<String, Object> map = ...;
Map<String, Object> filtered = CollectionUtils.filter(map, new Predicate<Map.Entry<String, Object>>() {
@Override
public boolean apply(Map.Entry<String, Object> entry) {
return isEntryOK(entry);
}
};
如果你实际上可以使用 Java 8,但由于某些原因你不能使用 Java 的流(例如 Android 开发支持旧版本 Android 与 Java 不兼容 8) 您可以删除语法建议并以更好的形式编写:
Map<String, Object> map = ...;
Map<String, Object> filtered = CollectionUtils.filter(
map,
entry -> isEntryOK(entry)
);
或者,我认为最好的解决方案 -> 切换到 Kotlin,它为您提供开箱即用的所有这些功能! :D
我有一个地图对象列表。这些地图对象有 properties/keys like id, condition_1, condition_2 等。示例地图看起来像这样,
List<Map<String, Object>> allItems = Lists.newArrayList();
Map<String, Object> paramsMap = Maps.newHashMap();
paramsMap.put("id", "a");
paramsMap.put("condition_1", false);
paramsMap.put("condition_2", true);
paramsMap.put("condition_3", false);
allItems.add(paramsMap);
因此,我需要过滤 allItems
对象,使其仅包含具有 condition_1 = true
和 condition_2 = false
等的地图对象。
我考虑过使用 apache commons CollectionUtils.filter 但这似乎并不能解决我的问题,因为我无法将映射条目指定为过滤条件。
我也不反对使用 Google 番石榴,但我找不到好的解决方案。
基本上,我试图模仿优秀的 JavaScript 库 underscore.js 中的 _.where
功能。
在 Java 8 中你可以使用流:
allItems.stream()
.filter(map->
(map.get("condition_1")==true)&&(map.get("condition_2")==false))
.forEach(System.out::println); //Example output
一个 Guava 解决方案:
Iterables.filter(allItems, new Predicate<Map<String, Object>>() {
@Override public boolean apply(Map<String, Object> map) {
return Boolean.TRUE.equals(map.get("condition_1"))
&& Boolean.FALSE.equals(map.get("condition_2"));
}
});
我认为您将不得不长期这样做。不幸的是 Java 映射不是 Iterable 类型,这意味着大多数常见的库没有针对它们的过滤函数。尝试这样的事情(我相信字符串在 java 中隐式为真,以防您担心您的第一个键值对):
```
boolean result = true;
boolean test = true;
List<Map<String, Object> resultList;
for(Map<String, Object> map : allitems) {
for(String key : map.keySet()) {
result = result && test && map.get(key);
test = !test;
}
if(result) {
resultList.add(map);
}
}
return resultList;
```
另一种可能性是将您的地图变成 KeyValue
s 的列表并使用 apache 映射和列表函数。最有可能的是,当您使用 java 7 时,您不会得到那个漂亮的衬垫。希望这对您有所帮助。
我认为最好的解决方案是实际执行与 Kotlin 在方法 Map<K, V>.filter
中所做的相同的操作。
让我们创建谓词:
public interface Predicate<T> {
boolean apply(T t);
}
Predicate 是一个对 functional-like 编程有用的接口。方法在满足条件时应用 returns true。
然后,像 CollectionUtils
一样创建 class 并在其中放置一个静态方法:
public static <K, V> Map<K, V> filter(
@NonNull Map<K, V> collection,
@NonNull Predicate<Map.Entry<K, V>> predicate
) {
Map<K, V> result = new HashMap<>();
for (Map.Entry<K, V> entry : collection.entrySet()) {
if (predicate.apply(entry) {
result.put(entry.getKey(), entry.getValue();
}
}
return result;
}
这样我们就可以按照以下方式使用这个方法:
Map<String, Object> map = ...;
Map<String, Object> filtered = CollectionUtils.filter(map, new Predicate<Map.Entry<String, Object>>() {
@Override
public boolean apply(Map.Entry<String, Object> entry) {
return isEntryOK(entry);
}
};
如果你实际上可以使用 Java 8,但由于某些原因你不能使用 Java 的流(例如 Android 开发支持旧版本 Android 与 Java 不兼容 8) 您可以删除语法建议并以更好的形式编写:
Map<String, Object> map = ...;
Map<String, Object> filtered = CollectionUtils.filter(
map,
entry -> isEntryOK(entry)
);
或者,我认为最好的解决方案 -> 切换到 Kotlin,它为您提供开箱即用的所有这些功能! :D