首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用Java 8 Stream API统计连续相同对象的数量

使用Java 8 Stream API统计连续相同对象的数量
EN

Stack Overflow用户
提问于 2018-06-27 16:45:27
回答 2查看 1.1K关注 0票数 2

我想用Java 8流一个接一个地计算相同对象的数量。我该怎么做?如果我有一份清单

代码语言:javascript
运行
复制
3, 3, 5, 5, 5, 6, 3, 3

我希望结果是

代码语言:javascript
运行
复制
[3-2] [5-3] [6-1] [3-2]

我在没有Java 8 streams的情况下的幼稚尝试:

代码语言:javascript
运行
复制
private static List<ValueCount> counteSameValueInRow(List<Integer> Values) {
    List<ValueCount> result = new ArrayList<ValueCount>();
    ValueCount valueCount = null;

    for (int value: Values) {
        if (valueCount == null) {
            valueCount = new ValueCount(value);
        } else if (valueCount.value == value){
            valueCount.numberof++;
        } else {
            result.add(valueCount);
            valueCount = new ValueCount(value);
        }
    }
    result.add(valueCount);
    return result;
}
EN

回答 2

Stack Overflow用户

发布于 2018-06-27 17:11:02

您正在做的事情可以与流上的collect相比较。将每个数字汇总到一个“组”列表中。Collectors.groupingBy()出现在脑海中,但这将对整个列表中的数字进行分组,即只计算每个数字的出现次数。使用Stream.collect(Supplier, BiConsumer, BiConsumer)方法实现自定义收集,您可以执行以下操作:

代码语言:javascript
运行
复制
List<Integer> values = Arrays.asList(3, 3, 5, 5, 5, 6, 3, 3);

values.stream().collect(LinkedList<List<Integer>>::new, (list, value) -> {
    if (list.isEmpty() || !list.getLast().get(0).equals(value))
    {
        list.add(new ArrayList<>());
    }
    list.getLast().add(value);
}, (list1, list2) -> {
    if (list1.getLast().get(0).equals(list2.getFirst().get(0)))
    {
        list1.getLast().addAll(list2.getFirst());
        list2.removeFirst();
    }
    list1.addAll(list2);
}).forEach(group -> System.out.println("[" + group.get(0) + "-" + group.size() + "]"));

请注意,我使用ArrayLists来收集重复项。您可以使用ValueCount类来实现此目的,这可能会使其更具可读性。

此示例中的流不会提高代码的可读性,但可以使用并行处理。看看collect方法的第三个参数。其中一个合并了两个中间结果,以防流被并行处理。

要并行尝试,请将stream()替换为parallelStream(),并在第三个参数的lambda中放置一个sysout,以查看两个中间结果何时合并。请注意,只有在列表非常大的情况下,并行处理才会使您受益。

票数 1
EN

Stack Overflow用户

发布于 2018-06-27 20:01:04

在Malte Hartwig的提议之后,我进行了重构以获得更好的可读性。结果如下所示

代码语言:javascript
运行
复制
 public static void main(String[] args) {
    List<Integer> values = Arrays.asList(3, 3, 5, 5, 5, 6, 3, 3);

    BiPredicate<Integer, Integer> predicate = (value1, value2) -> value1.equals(value2);

    Supplier<BiConsumer<LinkedList<ValueCount>, Integer>> accumulator = 
        () -> (list, value) -> {
        if (list.isEmpty() || !predicate.test(list.getLast().getFirstValue(), value)) {
            list.add(new ValueCount());
        }
        list.getLast().add(value);
    };

    Supplier<BiConsumer<LinkedList<ValueCount>, LinkedList<ValueCount>>> combiner = () -> (list1, list2) -> {
        if (list1.getLast().getFirstValue().equals(list2.getFirst().getFirstValue())) {
            list1.getLast().addAll(list2.getFirst());
            list2.removeFirst();
        }
        list1.addAll(list2);
    };

    values.stream().collect(LinkedList::new, accumulator.get(), combiner.get())
            .forEach(group -> System.out.println(group));
}

private static class ValueCount {
    private List<Integer> lista = new ArrayList<>();

    public String toString() { return "[" + lista.get(0) + "-" + lista.size() + "]";}
    public void add(Integer value) { lista.add(value);}
    public Integer getFirstValue() { return lista.get(0);}
    public void addAll(ValueCount first) { lista.addAll(first.getAll());}
    private Collection<? extends Integer> getAll() { return lista;}
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51058350

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档