Kotlin 收集示例#7b-使用SummarizingInt收集

示例

// Java:
IntSummaryStatistics ageSummary =
    persons.stream()
           .collect(Collectors.summarizingInt(p -> p.age));

System.out.println(ageSummary);
// IntSummaryStatistics {count = 4,sum = 76,min = 12,average = 19.000000,max = 23}
// 科特林:

// 保持统计数据的东西...
data class SummaryStatisticsInt(var count: Int = 0,  
                                var sum: Int = 0, 
                                var min: Int = Int.MAX_VALUE, 
                                var max: Int = Int.MIN_VALUE, 
                                var avg: Double = 0.0) {
    fun accumulate(newInt: Int): SummaryStatisticsInt {
        count++
        sum += newInt
        min = min.coerceAtMost(newInt)
        max = max.coerceAtLeast(newInt)
        avg = sum.toDouble() / count
        return this
    }
}

// 现在手动进行折叠,因为Stream.collect实际上只是折叠
val stats = persons.fold(SummaryStatisticsInt()) { stats, person -> stats.accumulate(person.age) }

println(stats)
// 输出:SummaryStatisticsInt(count = 4,sum = 76,min = 12,max = 23,avg = 19.0)

但是最好创建一个扩展功能,2实际上是要匹配Kotlin stdlib中的样式:

// 科特林:
inline fun Collection<Int>.summarizingInt(): SummaryStatisticsInt
        = this.fold(SummaryStatisticsInt()) { stats, num -> stats.accumulate(num) }

inline fun <T: Any> Collection<T>.summarizingInt(transform: (T)->Int): SummaryStatisticsInt =
        this.fold(SummaryStatisticsInt()) { stats, item -> stats.accumulate(transform(item)) }

现在,您有两种使用新summarizingInt功能的方法:

val stats2 =persons.map{it.age}.summarizingInt()

// 要么

val stats3 =persons.summarizingInt{it.age}

所有这些产生相同的结果。我们还可以创建此扩展,以在Sequence适当的原始类型上工作并适用于它们。