找出Java8流过滤器是否过滤了某些内容的优雅方法
我有一个从数据库中获取的找出Java8流过滤器是否过滤了某些内容的优雅方法,java,java-8,java-stream,Java,Java 8,Java Stream,我有一个从数据库中获取的项目的列表 我会这样做: List<Item> list; list.stream() .filter( i -> i.condition() ) .mapToLong( Item::asLong ) .sum() ; 列表; list.stream() .filter(i->i.condition()) .mapToLong(项目::asLong) .sum() ; 现在我想知道,过滤器是否过滤掉了一些东西,这样我就
项目的列表
我会这样做:
List<Item> list;
list.stream()
.filter( i -> i.condition() )
.mapToLong( Item::asLong )
.sum()
;
列表;
list.stream()
.filter(i->i.condition())
.mapToLong(项目::asLong)
.sum()
;
现在我想知道,过滤器是否过滤掉了一些东西,这样我就可以从不再需要的数据库中删除这些东西
我可以做到:
List<Item> list2 = list.stream()
.filter( i -> i.condition() )
.collect( Collectors.toList() )
;
int theSizeIWant = list2.size();
list2.stream().mapToLong( Item::asLong )
.sum()
;
List list2=List.stream()
.filter(i->i.condition())
.collect(收集器.toList())
;
int theSizeIWant=list2.size();
list2.stream().mapToLong(项::asLong)
.sum()
;
但是我想知道是否有一种更优雅的解决方案不需要创建中间列表。是的,您可以这样做
Map<Boolean, List<Item>> partitions =
list.stream.collect(Collectors.partitioningBy(i -> i.condition()));
映射分区=
list.stream.collect(收集器.partitioningBy(i->i.condition());
其中partitions.get(true)
将为您提供好的分区,而partitions.get(false)
将为您提供要删除的分区。一个可能的解决方案是使用谓词对流进行分区并求和值。分区是用。在这种情况下,谓词将是您的筛选函数,而下游收集器将是对值求和
public static void main(String[] args) {
List<Item> list = new ArrayList<>();
Map<Boolean, Long> map =
list.stream()
.collect(Collectors.partitioningBy(
Item::condition,
Collectors.summingLong(Item::asLong)
));
long sumWithTrueCondition = map.get(true);
long sumWithFalseCondition = map.get(false);
}
publicstaticvoidmain(字符串[]args){
列表=新的ArrayList();
地图=
list.stream()
.collect(收集器(
项目::条件,
收集器.summingLong(项::asLong)
));
long-sumWithTrueCondition=map.get(true);
long-sumWithFalseCondition=map.get(false);
}
映射将包含谓词为true
(resp.false
)且带有true
键(resp.false
)的和
这样,如果已过滤某些内容,sumWithTrueCondition
将严格大于0。此外,您可以通过添加sumWithTrueCondition
和sumWithFalseCondition
来获得总和。另一种解决方案是计算lambda表达式中的坏元素:
List<String> strings = Arrays.asList("1", "2", "3", "12", "4", "5");
List<String> badOnes = new ArrayList<>();
strings.stream()
.filter(s -> {
boolean returnValue = !s.contains("1");
if (!returnValue) {
badOnes.add(s);
}
return returnValue;
})
.forEach(s -> System.out.println(s));
System.out.println(badOnes);
List strings=Arrays.asList(“1”、“2”、“3”、“12”、“4”、“5”);
List badOnes=new ArrayList();
strings.stream()
.过滤器(s->{
布尔返回值=!s.contains(“1”);
if(!returnValue){
坏人。添加(s);
}
返回值;
})
.forEach->System.out.println;
系统输出打印项次(坏项次);
这减轻了中间列表的负担,但仍然需要进行第二次计算。如果某个东西没有通过条件,它就不会在流的下游传递,也不会被计数
int count = 0;
count必须是一个实例变量,然后您可以执行以下操作:
List<Item> list;
list.stream()
.filter( i -> i.condition() )
.mapToLong( (item) -> { count++; return item.asLong(); } )
.sum();
boolean isFiltered = list.size() > count;
列表;
list.stream()
.filter(i->i.condition())
.mapToLong((项)->{count++;return item.asLong();})
.sum();
布尔值isFiltered=list.size()>count;
list2.size()在第二个代码片段中是奇怪的for()
loop是优雅的…:)注意,这里有状态过滤器。这违反了过滤器
的约定。您对坏人的写入在这里不是线程安全的!这是一个即将发生的事故。使用线程安全的构造,如设置一个原子布尔值
。实际上,@Tunaki,filter参数不是有状态的,也没有干扰,因为它写入的状态没有用作流管道使用的任何计算的输入。但是,它仍然是错误的,因为它有副作用,而且副作用不是线程安全的。@BrianGoetz您能解释一下为什么这里要求线程安全吗?这不是只有在使用并行流时才会引起关注吗?@kingds,这要看情况而定。这有点像说“如果炉子上没有油布,把油布放在炉子上是安全的。”这是真的,但是。。。这仍然是一个相当不负责任的举动。您是否绝对肯定,在未来20年的代码维护中,不会有人试图将流并行化?你愿意把公司的生意押在这上面吗?正如我之前的评论所说,这是一个(很容易避免的)即将发生的事故。当然,只要你再也不碰它,它可能没问题,但这真的描述了软件在现实世界中是如何维护的吗?