在Java 7或更低版​​本中,HOWTO使用地图中找到的键/值过滤地图对象列表

时间:2015-01-16 17:13:35

标签: java collections underscore.js guava lambda

我有一个地图对象列表。这些地图对象具有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&amp;的映射对象。 condition_2 = false,&amp;等等&amp;等等。

我考虑过使用apache commons CollectionUtils.filter,但这似乎无法解决我的问题,因为我无法将地图条目指定为过滤条件。

我也不反对使用Google Guava,但我无法找到一个好的解决方案。

基本上我试图模仿优秀的JavaScript库underscore.js中的_.where功能。

4 个答案:

答案 0 :(得分:5)

一种番石榴解决方案:

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"));
   }
});

答案 1 :(得分:0)

我认为你必须做很长的事情。遗憾的是,Java Maps不是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;

```

另一种可能性是将Map转换为KeyValues列表并使用apache映射和列表函数。最有可能的是,当你使用java 7时,你不会那么漂亮。希望这有帮助。

答案 2 :(得分:0)

我认为最好的解决方案是实际上与Kotlin在方法Map<K, V>.filter中所做的相同。

让我们创建谓词:

public interface Predicate<T> {
    boolean apply(T t);
}

谓词是对类似函数的编程有用的接口。满足条件时,方法apply将返回true。

然后,创建类似CollectionUtils的类,并在其中放置一个静态方法:

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的流(例如,支持与Java 8不兼容的较旧版本的Android的Android开发),则可以删除语法的建议并以更好的形式编写: / p>

Map<String, Object> map = ...;
Map<String, Object> filtered = CollectionUtils.filter(
    map,
    entry -> isEntryOK(entry)
);

或者,我认为最好的解决方案-> 切换到Kotlin,即可为您提供所有这些功能! :D

答案 3 :(得分:-4)

在Java 8中,您可以使用流:

allItems.stream()
        .filter(map->
        (map.get("condition_1")==true)&&(map.get("condition_2")==false))
        .forEach(System.out::println); //Example output