使用每种类型的计数将数组转换为 Javaslang Map

Converting an Array to Javaslang Map with counts for each type

我目前正在查看 Javaslang 库,我正在尝试将我的一些代码转换为 Javaslang。

我目前有这段纯代码Java

Cell[][] maze; //from input
Map<Cell, Long> cellCounts = Stream.of(maze)
            .flatMap(Stream::of)
            .collect(groupingBy(c -> c, counting()));

我正在考虑将其转换为 Java 俚语,因为我对这个库很感兴趣,我只是想尝试一下。

我正在尝试做类似的事情,但转换为 Java 俚语映射而不是 java.util.Map。

到目前为止我已经尝试过了,但后来我卡住了,因为我看不到转换它的方法。

Array.of(maze)
     .flatMap(Array::of)

所以我有我的 Cell 对象列表,但我想弄清楚如何将其转换为 javaslang.collection.Map

*编辑*

我考虑过通过这个

将我原来的 java.util.Map 变成 javaslang.collections.Hashmap
HashMap<Cell, Long> cellsCount = HashMap.ofEntries(cellCounts
                                                        .entrySet()
                                                        .toArray(new Map.Entry[0]));

这似乎仍然不符合 Java俚语,但我会继续寻找。

通常分组依据有另一种方法,该方法采用您尝试转换为的 Map 实现,但它必须是实际扩展 java.util.Map:

的类型
Collectors.groupingBy(classifier, mapFactory, downstream)

据我所知,javaslang.collection.Map 是一个接口,而不是实际的实现。

由于没有可扩展 java.util.Map 的 javaslang 映射的实现,您所能做的就是创建一个自定义收集器。

或者已经收集到 java.util.Map - 将它们放入 javaslang.collection.Map 的某个实例中。

虽然 answer that Eugene 提供的一般情况下是正确的:有人 必须制作自定义收集器。

然而,这不一定是你:Java俚语专家已经为你解决了,通过提供必要的方法来具体实现 Javaslang 映射,这些方法将在最简单的情况下工作。例如,Java俚语 HashMap:

javaslang.collection.HashMap::collector()

public static <K,V> Collector<Tuple2<K,V>,ArrayList<Tuple2<K,V>>,HashMap<K,V>> collector()

Returns a Collector which may be used in conjunction with Stream.collect(java.util.stream.Collector) to obtain a HashMap.

Type Parameters:

K - The key type

V - The value type

Returns:

A HashMap Collector.

编辑: 然而,这似乎不一定有效,因为从收藏家的签名来看:

  1. 期望 Tuple<K,V>
  2. 的流
  3. 将该流的所有元素收集到 ArrayList<Tuple2<K,V>>
  4. 收集完所有元素后,它通过将 ArrayList 的所有内容添加到 HashMap 中来“完成”。

这显然是行不通的,因为您有 Stream<Cell>,并且您想要计算它们。然而,该签名实际上给了我们一些东西:它指出内置 Javaslang 收集器不会直接收集到 Javaslang Map(至少在 HashMap 中不会)。知道了这一点,我们可以寻找方法将 Java Map 转换为 Javaslang map,我们会发现:

javaslang.collection.HashMap::ofAll(java.util.Map)

Returns a HashMap, from a source java.util.Map.

我们可以像这样在您已有的方法之上添加此方法:

Stream<Cell> cells // <- you have this

cells.collect(
  collectingAndThen(
    groupingBy(Function.identity(), counting()),
    HashMap::ofAll
  )
);

您可以在 java.util.stream.Collectors.

中找到所有没有限定符的方法

此代码段将收集到正常的 Java Map,最后一步将调用 Collector 的 Finisher,它将 java Map 中的所有值放入 Javaslang map .

注意:我没有安装 Javaslang,无法测试上面的代码片段是否编译,但它看起来像你想要的那样。

免责声明:我是 Javaslang 的作者。

使用 Javaslang 实现它的最简单方法如下:

    Map<Cell, Integer> cellCounts = Array.of(maze)
            .flatMap(Array::of)
            .groupBy(c -> c)
            .mapValues(Array::length);

这里 ArrayMap 是从 javaslang.collection 导入的。

请注意,您可以将 Array 替换为任何其他 SeqSet 实现。