当前位置: 首页 > 知识库问答 >
问题:

对另一个流进行流过滤并计数

凌修伟
2023-03-14

我需要基于另一个流过滤一个流,并获取所有匹配条目的计数。

我已经尝试了以下和各种其他组合,但它没有按预期工作。

这个想法是:

    < li >对于从0到256的每个数字(流1) < li >查看该号码是否出现在另一个列表中(流2 ),如果出现的话 < li >计算出现次数除以流2中的元素总数(18)。 < li >如果没有出现,请收集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());

共有3个答案

酆鸿彩
2023-03-14

其他解决方案的替代方案(在迭代给定流的元素方面是有效的)但更接近您现有的尝试是将输入用作数组,以便能够在处理它们时使用大小维度,而不是执行anyMatch,只需简单地过滤器ing和计数元素以进一步执行平均操作:

int[] chars = new int[]{332, 255, 271, 232, 194, 39, 162, 89, 200, 126, 225, 218, 42, 237, 87, 63, 63, 229};
List<Double> fractions = IntStream.rangeClosed(0, 256)
        .mapToLong(value -> Arrays.stream(chars).filter(f -> value == f).count())
        .mapToDouble(x -> (double) x / chars.length).boxed()
        .collect(Collectors.toList());
暴德运
2023-03-14

我会做一点不同的事情,更一般地处理手头的问题:

IntStream idents = ...; // Your 0-256
IntStream input = ...; // your random numbers

//Generate a map of input numbers to how often they occur
Map<Integer, Long> freq = input.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
//No need for the stream's source, use the map
long total = freq.values().stream().reduce(0L, Long::sum); // your 18

使用我们的频率图,可以轻松创建我们想要的内容。我做了一个我的建议的答案,以及一个满足您要求的答案:

//Generating the 0-256 array in double form
double[] result = idents.mapToDouble(i -> freq.getOrDefault(i, 0) / (double) total).toArray();

老实说,我认为仅仅使用频率图来确定您需要的信息没有多大意义:

//Find the fraction for 39:
double value = freq.getOrDefault(39, 0) / (double) total;

//Find only the values in range:
Predicate<Integer> inRange = i -> i >= 0 && i <= 256;
freq.entrySet().stream().filter(e -> inRange.test(e.getKey())); //you now have a stream of the valid frequencies

//Or the values out of range
....filter(e -> inRange.negate().test(e.getKey()))

如果输入是空的,你也可以直接返回数组。如果还有我没有提到的例子,请告诉我

慕容齐智
2023-03-14

您应该避免迭代源256次。对于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());
        }));

但使用流或“一次操作”本身并不是目的。

如果您想要一个简单高效的解决方案,请考虑

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());
 类似资料:
  • 问题内容: 我在此论坛和Google中搜索后发布了查询,但无法解决相同的问题。 我正在尝试根据列表1中的值过滤列表2(多列)。 码 在上面的代码中,如果我提供特定值,则可以过滤,但不确定如何检查列表2中的Car Name是否在列表1中退出。 希望我面对的问题很清楚,等待指导(对于Java来说还是比较新的,因此,如果上述查询非常基础,请原谅)。 编辑, 我相信上面提供的链接3应该可以解决,但就我而言

  • 我一直在检查Kafka流。我一直在测试下面的Kafka流代码 生产者主题:(这是第一个生产者主题-发送以下json数据) JSON-主题的生产者: Stream Topic代码:(这是第二个Streaming代码和主题) 如果UserID值为“1”,我想对其进行归档,然后将该数据发送到目标流媒体主题。 当我使用“.filter”并打印System.out时。println(“value:”valu

  • 我想在spring batch中实现如下的流结构。 作业配置伪代码如下: 当我运行批处理时,日志显示执行了步骤1、步骤2、步骤3和步骤5,但没有运行步骤4。 我想知道如何在另一个流中定义子流,上面的代码是实现它的正确方法吗? 提前谢谢!

  • 问题内容: 问:我怎样才能从读到的一切入的方式是不是一个手工制作的循环用我自己的字节的缓冲区? 问题答案: 编写一个方法来执行此操作,然后从需要该功能的任何地方调用它。番石榴已经在中提供了代码。我敢肯定,几乎所有其他具有“通用” IO功能的库也都有它,但是Guava是我第一个“入门”库。它震撼了:)

  • 我想要找到合适的正则表达式匹配的行数。输入是通过Java Stream插入的日志文件。我想对这个流应用多个过滤器,但每隔一段时间计算一次。