[英]Java 8 lambda error: filter stream by reduced filter collection THEN map THEN collect
[英]Java Stream Map Filter, Remove and Collect
我有一个包含 1000 个项目的Map
,我想从此Map
的前 500 个项目生成一个List
,并删除从Map
收集的项目。
换句话说,我想过滤、收集到List
并从Map
中删除项目。
我正在尝试这样的事情:
final int i = 0;
int max = 5;
Map<String, Object> map = new HashMap<>();
map.put("ads", "123");
map.put("qwe", "123");
map.put("cvb", "123");
map.put("asd", "123");
map.put("iop", "123");
map.put("jkl", "123");
map.put("yui", "123");
List list = map.entrySet().stream().filter(y -> i++ < max).collect(Collectors.toList());
预期 output:
Map 有 2 个值
包含 5 个值的列表
Stream API 旨在创建一个新集合,但不更改现有集合,从中创建一个 stream。
在这种情况下最好使用迭代器功能。 像这样:
final int MAX = 500;
Map<String, String> map = new HashMap<>();
map.put("Item1", "Item 1 value");
map.put("Item2", "Item 2 value");
// ...
map.put("Item1000", "Item 1000 value");
List<String> list = new ArrayList<>();
var iterator = map.entrySet().iterator();
for (int i = 0; i< MAX; i++) {
if (iterator.hasNext()) {
var item = iterator.next();
list.add(item.getValue());
iterator.remove();
}
}
正如在其他答案和评论中指出的那样,您不能在流操作期间更改 map。 所以这需要两个步骤。
var list = map.keySet().stream().limit(500).toList();
map.keySet().removeAll(list);
我在这里使用了 Java 16 API 但以前的版本是微小的变化。
但是请注意,鉴于未定义地图的顺序,这是一件毫无意义的事情。 如果您使用带有某些谓词的过滤器,那将更有意义。 尽管在这种情况下,更易读的替代方案可能是:
var list = map.keySet().stream().filter(predicate).toList();
map.keySet().removeIf(predicate);
使用SINGLE STREAM实现此目的的最简单方法是使用Stream#limit
、 Collectors#collectingAndThen
并在第二个下游Collector
内执行removeAll
这是可能的,因为第一个Collectors.toList
将摆脱地图的迭代,然后第二个操作可以删除而不会出现异常
List<Map.Entry<String, Object>> list = map.entrySet()
.stream()
.limit(max)
.collect(Collectors.collectingAndThen(
Collectors.toList(),
l -> {
map.entrySet().removeAll(l);
return l;
}
));
System.out.println("map = " + map); // map = {qwe=123, cvb=123}
System.out.println("list = " + list); // list = [ads=123, asd=123, jkl=123, iop=123, yui=123]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.