简体   繁体   English

从流中的两个列表创建隔离值的映射

[英]Create map of segregated values from two lists in stream

I'm trying to create map of two lists. 我正在尝试创建两个列表的地图。 First List is used for keys and second to segregate and assign values, wherein situation, where there are no values matching bin assigned, will be empty List. First List用于键,第二列用于隔离和赋值,其中没有匹配bin的值的情况将是空List。 Values should be assigned like to key 5 values <50, 60), so having 值应分配给键值5 <50,60),因此具有

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

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

I'd like to have Map that will have keys: 0, 1, 2, 3, 4, 5, 6. Empty Lists for key 1, 2, 3, 4, 6. List out of 5, 6 assigned to key 0 and 55, 52 assigned to 5. 我想要有一个具有键的地图:0,1,2,3,4,5,6。键1,2,3,4,6的空列表。列出5,6分配给键0分配给5,55,52。

Right now I have it like this, it's working but I'm searching for something better, for example, solution that will not require sampleBins and will fit in one pipeline 现在,我有这样的,它正在工作,但我正在寻找更好的东西,例如,解决方案,不需要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);
}

Here's my first solution, which essentially combines yours into a single statement. 这是我的第一个解决方案,它基本上将您的解决方案整合到一个声明中。 Note that this is expensive to perform with large lists, so I will look for something more efficient in the meantime: 请注意,使用大型列表执行此操作非常昂贵,因此在此期间我会寻找更高效的内容:

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

This outputs the following: 这输出如下:

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

Here is another solution which is pretty simple: 这是另一个非常简单的解决方案:

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

However, it will output the following instead of setting the other bins to empty List s, which may or may not be a problem in your case since you can simply check if the bin exists as a key in the Map : 但是,它将输出以下内容,而不是将其他容器设置为清空List s,这可能是您的情况可能是也可能不是问题,因为您只需检查bin是否作为Map的键存在:

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

I'll edit my post if I find anything else interesting, so keep an eye out! 如果我发现其他有趣的东西,我会编辑我的帖子,所以请留意!

It seems to me that the method to classify your samples is fixed. 在我看来,对样本进行分类的方法是固定的。 The only difference the bins are making is to specify what you are interested in. Therefore, in the first place, there is no too much need to pay attention to your bins. 箱子的唯一区别是指定你感兴趣的东西。因此,首先,没有太多需要注意你的箱子。

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

    Map<Integer, List<Integer>> groupedSamples = samples.stream().collect(Collectors.groupingBy(x -> 10 * x / 10));

    return sampleBins.stream().collect(Collectors.toMap(Function.identity(), b -> 
            groupedSamples.getOrDefault(b, Collections.emptyList())));
}

This function first groups your samples, then based on your interested bins, either extract list out of the map, or create a empty list if it's absent. 此函数首先对您的样本进行分组,然后根据您感兴趣的分类,从地图中提取列表,或者如果不存在则创建一个空列表。

How about concat lists and then create single parallel stream? 如何将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))));
}

The only disadvantage is that every collection contains its key. 唯一的缺点是每个集合都包含其密钥。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM