Filter Map<String,List<Object>> 使用 Java 流

Filter Map<String,List<Object>> Using Java Streams

class Custom{
   String itemId,
   long createdTS
   //constructor
   public Custom(String itemId,long createdTS)
}

我有两张地图

Map<String,Long> itemIDToFilterAfterTS;
Map<String,List<Custom>> itemIDToCustoms;

我想使用 java 流使用第一个地图 itemIDToTimestampMap 值过滤第二个地图 itemIDToCustoms 值。 例如

itemIDToFilterAfterTS = new HashMap();
itemIDToFilterAfterTS.put("1",100);
itemIDToFilterAfterTS.put("2",200);
itemIDToFilterAfterTS.put("3",300);

itemIDToCustoms = new HashMap();
List<Custom> listToFilter = new ArrayList();
listToFilter.add(new Custom("1",50));
listToFilter.add(new Custom("1",90));
listToFilter.add(new Custom("1",120));
listToFilter.add(new Custom("1",130));
itemIDToCustoms.put("1",listToFilter)

现在我想使用 java 流并想要过滤结果映射,其中 getKey("1") 给出已创建 TS > 100 的自定义对象的过滤列表(将从 [=22 获取 100 =]("1"))

Map<String,List<Custom>> filteredResult will be 
Map{
   "1" : List of (Custom("1",120),Custom("1",130))
}  

这里的流语法有点多

itemIDToCustoms = itemIDToCustoms.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(),
            e -> e.getValue().stream().filter(val -> val.createdTS > itemIDToFilterAfterTS.get(e.getKey())).collect(Collectors.toList())));

使用 for 循环 + 流更具可读性

for (Map.Entry<String, List<Custom>> e : itemIDToCustoms.entrySet()) {
    long limit = itemIDToFilterAfterTS.get(e.getKey());
    List<Custom> newValue = e.getValue().stream().filter(val -> val.createdTS > limit).collect(Collectors.toList());
    itemIDToCustoms.put(e.getKey(), newValue);
}

您可以使用这样的Map#computeIfPresent方法:

如果键已经与值相关联,则允许您计算指定键的映射值

public Object computeIfPresent(Object key,BiFunction remappingFunction)

所以你可以这样执行:

itemIDToFilterAfterTS.forEach((key, value) ->
            itemIDToCustoms.computeIfPresent(key, (s, customs) -> customs.stream()
                    .filter(c -> c.getCreatedTS() > value)
                    .collect(Collectors.toList())));