查找通过给定条件的N个第一个元素:求和到给定数量

时间:2019-02-27 08:57:52

标签: java lambda collections java-8 java-stream

我有Pocket个实例的列表

List<Pocket> pockets;

其中Pocket类如下所示:

public class Pocket {
    String name;
    Double amount;
}

口袋列表示例:

[
    {"pocket1", 280},
    {"pocket2", 320},
    {"pocket3", 100},
    {"pocket4", 125},
    {"pocket5", 150},
    {"pocket6", 175}
]

我需要找到n个第一口袋,它们可以一起从给定的口袋列表中提供N(例如650)。如果最后一个口袋的amount大于所需的口袋,则应将该口袋分成两个口袋,结果列表应仅包含一部分,再加上之前的n - 1口袋将得到N。 / p>

例如,我需要按顺序排列的衣袋清单,就像在源清单中将总数650相加一样。请注意,3-rd个口袋被拆分了,只有amount的一半返回了最后一个口袋:

[
    {"pocket1", 280},
    {"pocket2", 320},
    {"pocket3", 50}
]

如何使用Java Streams来实现它?

1 个答案:

答案 0 :(得分:1)

您可以使用flatMapStream来做到这一点。参见以下示例:

import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Stream;

public class Lambda {

    public static void main(String[] args) {
        List<Pocket> pockets = Arrays.asList(
            new Pocket("pocket1", 280D),
            new Pocket("pocket2", 320D),
            new Pocket("pocket3", 100D),
            new Pocket("pocket4", 50D));

        System.out.println("Filtered");
        pockets.stream()
            .flatMap(new SplitFunction(651))
            .forEach(System.out::println);

        System.out.println("Original");
        pockets.forEach(System.out::println);
    }
}


class SplitFunction implements Function<Pocket, Stream<Pocket>> {

private double max;

public SplitFunction(double max) {
    this.max = max;
}

@Override
public Stream<Pocket> apply(Pocket pocket) {
    if (Double.compare(max, pocket.amount) >= 0) {
        max -= pocket.amount;
        return Stream.of(pocket);
    } else if (Double.compare(max, 0.0) > 0) {
        Pocket lastPocket = new Pocket(pocket.name, max);
        max = 0;

        return Stream.of(lastPocket);
    }
    return Stream.empty();
}
}

上面的代码显示:

Filtered
Pocket{name='pocket1', amount=280.0}
Pocket{name='pocket2', amount=320.0}
Pocket{name='pocket3', amount=51.0}
Original
Pocket{name='pocket1', amount=280.0}
Pocket{name='pocket2', amount=320.0}
Pocket{name='pocket3', amount=100.0}
Pocket{name='pocket4', amount=50.0}