从流

时间:2018-02-24 12:12:55

标签: java java-8 java-stream

我试图创建两个列表的地图。 First List用于键,第二列用于隔离和赋值,其中没有匹配bin的值的情况将是空List。应该将值分配给键值5 <50,60),因此具有

  

sampleBins = Arrays.asList(0,10,20,30,40,50,60);

     

samples = Arrays.asList(5,6,55,52);

我希望地图有关键:0,1,2,3,4,5,6。 键1,2,3,4,6的空列表。 列表中的5个,6个分配给键0和55,52分配给5。

现在我有这样的,它正在工作,但我正在寻找更好的东西,例如,解决方案不需要sampleBins并且适合一个管道

private Map<Integer, List<Integer>> segregateSamples(List<Double> sampleBins, List<Double> samples) {

    Map<Integer, List<Integer>> segregatedSamples = sampleBins.stream()
        .collect(Collectors.toMap(bin -> bin.intValue() / 10, bin -> new ArrayList<>()));

    samples.stream()
        .map(Double::intValue)
        .collect(Collectors.groupingBy(this::binNumber))
        .forEach(segregatedSamples::put);

    return segregatedSamples;
}

private Integer binNumber(int value) {
    return Math.floorDiv(value, 10);
}

2 个答案:

答案 0 :(得分:1)

这是我的第一个解决方案,它基本上将您的解决方案整合到一个声明中。请注意,使用大型列表执行此操作非常昂贵,因此我会在此期间寻找更高效的内容:

sampleBins.stream()
          .collect(Collectors.toMap(bin -> bin / 10, bin ->
              samples.stream()
                     .filter(i -> i - i % 10 == bin)
                     .collect(Collectors.toList())
          ));

这输出以下内容:

  

{0 = [5,6],1 = [],2 = [],3 = [],4 = [],5 = [55,52],6 = []}

这是另一个非常简单的解决方案:

samples.stream().collect(Collectors.groupingBy(i -> i - i % 10));

但是,它会输出以下内容,而不是将其他分档设置为空List s,这可能是您的案例中可能有问题,也可能不是,因为您可以简单地检查bin是否作为密钥存在于Map

  

{0 = [5,6],50 = [55,52]}

如果我发现其他任何有趣内容,我会编辑我的帖子,所以请留意!

答案 1 :(得分:1)

如何使用concat列表然后创建单个并行流?

private Map<Integer, Collection<Integer>> segregateSamples(List<Double> sampleBins, List<Double> samples) {
    Stream<Double> d = Stream.concat(sampleBins.stream(), samples.stream()).parallel();
    return d.collect(Collectors.groupingByConcurrent(p -> (p.intValue() / 10),
                    Collectors.mapping(Double::intValue, Collectors.toCollection(ArrayDeque::new))));
}

唯一的缺点是每个集合都包含其密钥。