如何在 Kotlin 流中使用sortedByDescending?

问题描述 投票:0回答:1

我正在尝试在 Kotlin 中构建一个流解决方案

  1. 从标准输入中读取代表球员球队、姓名、比赛和分数的行
  2. 筛选出参加过15场或以上比赛的球员
  3. 按场均得分降序对球员进行排序
  4. 打印前十名此类球员。

在 Java 中,我能够在“单个”流中完成此操作

    // JAVA SOLUTION - WORKS
    new BufferedReader(new InputStreamReader(System.in))
        .lines()
        .map(line -> line.split(","))
        .map(Player::fromLine)
        .filter(p -> p.games >= 15)
        .sorted((p1, p2) -> Double.compare(p2.ppg, p1.ppg))
        .limit(10)
        .map(Player::reportLine)
        .forEach(System.out::println);

在上面的 Java 代码中,我创建了一个

Player
记录,其
fromLine
静态方法执行字符串到数字的转换,并使用在
ppg
字段中计算的每场比赛得分创建玩家记录。

但是,我无法直接将其翻译为 Kotlin。我试过:

// KOTLIN ATTEMPT - THIS DOES NOT WORK
BufferedReader(InputStreamReader(System.`in`))
    .lines()
    .map { it.split(",") }
    .map { Player.fromLine(it) }
    .filter { it.games >= 15 }
    .sortedByDescending { it.ppg }  // ERROR ON THIS LINE
    .take(10)
    .map { it.reportLine() }
    .forEach { println(it) }

错误是(毫不奇怪)

错误:未解析的参考。由于接收器类型不匹配,以下候选者均不适用:...

我认为这是因为

sortedByDescending
希望它的接收器是一个数组或一个可迭代的(我从文档中知道)。我已经解决了这个问题,并通过两步操作让我的代码正常工作:

// KOTLIN SOLUTION - WORKS (but can it done in one shot?)
val players = BufferedReader(InputStreamReader(System.`in`))
    .lines()
    .map { it.split(",") }
    .map { Player.fromLine(it) }
    .filter { it.games >= 15 }
    .toList()

players.sortedByDescending { it.ppg }
    .take(10)
    .map { it.reportLine() }
    .forEach { println(it) }

有什么方法可以将排序“放入单个流中”吗?

我想一个更深层次的问题可能是,为什么在非工作解决方案中的

filter
调用之前,
sortedByDescending
调用的结果没有产生正确的可迭代对象?

kotlin generics stream
1个回答
0
投票

我不太确定您是否计划使用 Java stdlib 中的

Stream
或 Kotlin stdlib 中的
Sequence
。您使用的运算符 (
take()
sortedByDescending()
) 是 Kotlin 的典型操作符,但您使用与 Java 中完全相同的
.lines()
函数,因此它返回 Java 的典型 API (
Stream
)。

要解决此问题,您需要坚持使用 Java API,因此请像在 Java 代码中一样使用

sorted()
limit()
。或者您需要坚持使用 Kotlin API,因此请使用
lineSequence()
而不是
lines()

© www.soinside.com 2019 - 2024. All rights reserved.