【问题标题】:How to filter and map a 2D IntArray into a Set using streams如何使用流过滤和映射 2D IntArray 到 Set
【发布时间】:2017-12-22 19:33:28
【问题描述】:

我有一个 2D IntArray 代表一个游戏板,其中 -1 表示一个空白区域,一些值大于或等于 0 表示该单元格属于某个玩家。如下所示(-1 由点(.)表示)

. . . . . 
1 0 . . 2
0 . 1 3 3
4 3 . . 0

我想获得一个Set,其中包含已被任何玩家占据的单元格的位置。像这样的:

[Cell{1,0}, Cell{1,1}, ..., Cell{3,4}]

我知道第一种方法是遍历二维数组:

val set = HashSet<Cell>();
for(row in 0 until HEIGHT){
    for (col in 0 until WIDTH){
        if(board[row][col] >= 0)
            set.add(Cell(row, col))
    }
}

但是...如果我使用流,效率会更高吗?能否以更少的代码更高效地实现?

IntStream.range(0, HEIGHT)
            .mapToObj { row -> IntStream.range(0, WIDTH)
                    .filter{ col -> board[row][col] >= 0}
                    .mapToObj { col -> Cell(row, col) } }
            .flatMap { point -> point }
            .collect(Collectors.toSet())

【问题讨论】:

    标签: arrays kotlin java-stream


    【解决方案1】:

    首先,建议使用 Kotlin 标准库而不是 Java 流。在 Kotlin 标准库 s1m0nw1 gave a good solution 中,我只需将 flatMap 替换为 flatMapTo 调用,以避免创建以后被丢弃的列表:

    val set = HashSet<Cell>()
    (0 until board.size).flatMapTo(set) { row ->
        (0 until board[row].size).filter { col ->
            board[row][col] >= 0
        }.map { col ->
            Cell(row, col)
        }
    }
    

    如果你真的需要 Java8 流解决方案,请使用以下代码:

    fun IntRange.stream() : Stream<Int>
        = StreamSupport.stream(spliterator(), false)
    
    val set = (0 until board.size).stream().flatMap { row ->
        (0 until board[row].size).stream().filter { col ->
            board[row][col] >= 0
        }.map { col ->
            Cell(row, col)
        }
    }.collect(Collectors.toSet())
    

    就性能而言,这里给出的两个解决方案应该非常相似(虽然我还没有测试过)。但是,Java8 流允许您并行执行操作(请参阅StreamSupport.stream)。这是使用一些线程池来为你做所有的魔法。据我所知,Kotlin 不提供任何开箱即用的并行操作,但它的 Coroutines 比 Java 线程快得多 - 但您可以使用更多代码。

    【讨论】:

      【解决方案2】:

      如果 Java 流被范围替换,这可以让 Kotlin 更自然一些。

      val cells = (0 until board.size).flatMap { row ->
          (0 until board[row].size)
                  .filter { col -> board[row][col] >= 0 }.map { Cell(row, it) }
      }.toSet()
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-22
        • 1970-01-01
        • 2021-09-18
        • 2022-01-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多