簡體   English   中英

使用Stream和java8在一個字符串中返回最小,最大,平均,總和,薪金計數

[英]Return in one string the min, max, average, sum, count of salaries with Stream and java8

我有一份以薪水為特征的雇員List 為什么此代碼不起作用?

String joined = employees.stream().collect(
    Collectors.summingInt(Employee::getSalary),
    Collectors.maxBy(Comparator.comparing(Employee::getSalary)),
    Collectors.minBy(Comparator.comparing(Employee::getSalary)),
    Collectors.averagingLong((Employee e) ->e.getSalary() * 2),
    Collectors.counting(),
    Collectors.joining(", "));

我正在使用一套收集器。

請注意,當前您嘗試獲取的不是最高/最低薪水,而是擁有該薪水的雇員。 如果您實際上想獲得最高/最低工資本身(數字),則可以使用Collectors.summarizingInt()一次計算這些特征:

IntSummaryStatistics stats = employees.stream()
    .collect(Collectors.summarizingInt(Employee::getSalary));

如果要將它們連接為字符串,則可以使用:

String statsString = Stream.of(stats.getSum(), stats.getMax(), stats.getMin(), 
                               stats.getAverage()*2, stats.getCount())
                           .map(Object::toString)
                           .collect(Collectors.joining(", "));

如果您確實想獲得薪水最高/最低的Employee,則此處IntSummaryStatistics不會為您提供幫助。 但是,您可以改為創建收集器流:

String result = Stream.<Collector<Employee,?,?>>of(
            Collectors.summingInt(Employee::getSalary),
            Collectors.maxBy(Comparator.comparing(Employee::getSalary)),
            Collectors.minBy(Comparator.comparing(Employee::getSalary)),
            Collectors.averagingLong((Employee e) ->e.getSalary() * 2),
            Collectors.counting())
        .map(collector -> employees.stream().collect(collector))
        .map(Object::toString)
        .collect(Collectors.joining(", "));

請注意,通過這種方式,您將獲得類似(取決於Employee.toString()實現的輸出:

1121, Optional[Employee [salary=1000]], Optional[Employee [salary=1]], 560.5, 4

不要忘記maxBy / minBy返回Optional


如果您對第一個解決方案不滿意,並且由於某種原因不想多次迭代輸入,則可以使用以下方法創建組合的收集器:

/**
 * Returns a collector which joins the results of supplied collectors
 * into the single string using the supplied delimiter.
 */
@SafeVarargs
public static <T> Collector<T, ?, String> joining(CharSequence delimiter, 
        Collector<T, ?, ?>... collectors) {
    @SuppressWarnings("unchecked")
    Collector<T, Object, Object>[] cs = (Collector<T, Object, Object>[]) collectors;
    return Collector.<T, Object[], String>of(
        () -> Stream.of(cs).map(c -> c.supplier().get()).toArray(), 
        (acc, t) -> IntStream.range(0, acc.length)
            .forEach(idx -> cs[idx].accumulator().accept(acc[idx], t)), 
        (acc1, acc2) -> IntStream.range(0, acc1.length)
            .mapToObj(idx -> cs[idx].combiner().apply(acc1[idx], acc2[idx]))
            .toArray(), 
        acc -> IntStream.range(0, acc.length)
            .mapToObj(idx -> cs[idx].finisher().apply(acc[idx]).toString())
            .collect(Collectors.joining(delimiter)));
}

有這樣的方法,你可以寫

String stats = employees.stream().collect(joining(", ",
        Collectors.summingInt(Employee::getSalary),
        Collectors.maxBy(Comparator.comparing(Employee::getSalary)),
        Collectors.minBy(Comparator.comparing(Employee::getSalary)),
        Collectors.averagingLong((Employee e) ->e.getSalary() * 2),
        Collectors.counting()));

我終於找到了解決方案。。謝謝嘗試的家伙

String s = employees.stream().mapToDouble(a>a.getSalary()).summaryStatistics().toString();

這是輸出:

 DoubleSummaryStatistics{count=21, sum=17200,000000, min=100,000000,
 average=819,047619, max=2100,000000}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM