我需要根据另一个流过滤一个流并获取所有匹配条目的计数。
我已经尝试了以下和各种其他组合,但它没有按预期工作。
想法是:
- 对于 0 到 256 之间的每个数字(流 1)
- 查看该号码是否出现在另一个列表(流 2)中以及是否出现
- 计算流 2 中的出现次数除以元素总数(18)。
- 如果没有出现,则收集 0。
这基本上是根据流 2 中的出现次数查找流 1 中数字的频率。
流 2 是
int[] chars = {332, 255, 271, 232, 194, 39, 162, 89, 200, 126, 225, 218, 42, 237, 87, 63, 63, 229};
以下代码的预期输出是:
[0,0,0,...,1/18for39,0,0,1/18for42,0,0,...,2/18for63,...,1/18for87,0,1/18for89,...1/18for126,0,0,...1/18for162,0,0,...,etc..1/18for255,0]
非常感谢任何帮助。提前致谢。
BiPredicate<Integer, Integer> predicate = (d, f) -> Integer.valueOf(d)
.equals(Integer.valueOf(f));
List<Double> fractions = chars.filter(value -> IntStream.rangeClosed(0, 256)
.anyMatch(nbr -> predicate.test(value, nbr)))
.count()
.map(x -> x)
.mapToDouble(x -> x / chars.size())
.boxed()
.collect(Collectors.toList());
最佳答案
您应该避免迭代源代码 256 次。对于 Stream,您无论如何都不能多次处理它,但即使您有一个允许多次迭代的源,在可以避免的情况下,您也不应该经常这样做。
如果你想让它看起来像一个单一的 Stream 操作,你可以这样做,例如
int[] chars = {332, 255, 271, 232, 194, 39, 162, 89, 200, 126, 225, 218, 42, 237, 87, 63, 63, 229};
List<Double> fractions = Arrays.stream(chars).boxed()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(Function.identity(), Collectors.counting()),
map -> {
double total = map.values().stream().mapToInt(Long::intValue).sum();
return IntStream.rangeClosed(0, 256)
.mapToObj(i -> map.getOrDefault(i, 0L)/total)
.collect(Collectors.toList());
}));
但是使用 Stream 或“一个操作”本身并不是目的。
如果您想要一个简单高效的解决方案,请考虑
int[] counts = new int[257];
for(int c: chars) if(c >= 0 && c <= 256) counts[c]++;
double total = chars.length;
List<Double> fractions
= Arrays.stream(counts).mapToObj(c -> c/total).collect(Collectors.toList());
关于java - 对另一个流进行流过滤并计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57465353/