我最近开始使用collectionAndThen,发现与我用来执行类似任务的其他编码过程相比,它花费了一些时间。

这是我的代码:

        System.out.println("CollectingAndThen");
        Long t = System.currentTimeMillis();
        String personWithMaxAge = persons.stream()
                                        .collect(Collectors.collectingAndThen(
                                                                Collectors.maxBy(Comparator.comparing(Person::getAge)),
                                                                (Optional<Person> p) -> p.isPresent() ? p.get().getName() : "none"
                                                ));


        System.out.println("personWithMaxAge - "+personWithMaxAge + " time taken = "+(System.currentTimeMillis() - t));
        Long t2 = System.currentTimeMillis();
        String personWithMaxAge2 = persons.stream().sorted(Comparator.comparing(Person::getAge).reversed())
                                                    .findFirst().get().name;
        System.out.println("personWithMaxAge2 : "+personWithMaxAge2+ " time taken = "+(System.currentTimeMillis() - t2));


这是输出:

CollectingAndThen
personWithMaxAge - Peter time taken = 17
personWithMaxAge2 : Peter time taken = 1


这表明collectionAndThen相较之下花费的时间更长。

所以我的问题是-我应该继续收集AndThen还是有其他建议?

最佳答案

collectingAndThen添加一个仅在集合末尾执行的操作。

所以

String personWithMaxAge = persons.stream()
    .collect(Collectors.collectingAndThen(
        Collectors.maxBy(Comparator.comparing(Person::getAge)),
        (Optional<Person> p) -> p.isPresent() ? p.get().getName() : "none"
    ));


与...没有什么不同

Optional<Person> p = persons.stream()
    .collect(Collectors.maxBy(Comparator.comparing(Person::getAge)));
String personWithMaxAge = p.isPresent() ? p.get().getName() : "none";


当您使用结果收集器作为另一个收集器(例如, groupingBy(f1, collectingAndThen(collector, f2))

由于这是一个简单的动作,仅在最后执行一次,因此对性能没有影响。此外,对于任何无关紧要的输入,基于sorted的解决方案不可能比maxBy操作更快。

您只是在使用破坏基准,违反了“ How do I write a correct micro-benchmark in Java?”中列出的一些规则。最值得注意的是,您正在测量Stream框架的首次使用的初始初始化开销。只需交换两个操作的顺序,您将获得完全不同的结果。

仍然不需要使操作不必要地复杂。如前所述,收集器镜像现有Stream操作的优点是它们可以与其他收集器组合。如果不需要这种组合,只需使用简单代码

String personWithMaxAge = persons.stream()
    .max(Comparator.comparing(Person::getAge))
    .map(Person::getName).orElse("none");


它比Collector的用法更简单,并且比基于sorted的解决方案更有效。

08-05 01:24