2017-03-01 41 views
6

我正在查看Javaslang库,我正在尝试将一些代码转换为Javaslang。将数组转换为Javalang映射每种类型的计数

目前,我有这段代码是所有纯Java

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

我一直在寻找这个转换为Javaslang,因为我感兴趣的图书馆,我只是想玩弄它。

我想做一个类似的事情,但转换为java.lang映射而不是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])); 

这仍似乎没有要与Javaslang线,但我将继续寻找。

+0

是否有扩展'java.util.Map'的'javaslang.collection.Map'的任何实现? – Eugene

+0

不,从头开始重写了javaslang.collection.Map。他们采用了功能性的方法来设计它,并使所有的集合都不可变。 – Ash

+0

Inmutable集合总是不是一个好主意。这取决于集合的大小 – xiumeteo

回答

2

声明:我是Javaslang的作者。

与Javaslang实现它这个最简单的方法是:

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

这里ArrayMapjavaslang.collection进口。

请注意,您可以用Array替代其他SeqSet实现。

+0

谢谢丹尼尔,我一直关注javaslang一点,所以当我看到它是你的用户回答我很高兴。 – Ash

+1

嗨阿什,是的 - 我记得你:) –

4

一般分组由具有另一种是在试图将转换为一个地图的实现方法,但它必须是实际上是扩展了java.util.Map的类型:

Collectors.groupingBy(classifier, mapFactory, downstream) 

从我看到javaslang.collection.Map是一个接口,而不是一个实际的实现。

由于没有实现可以扩展java.util.Map的javaslang Map,所以您只需创建自定义收集器。

或者一旦收集到java.util.Map - 将这些放入javaslang.collection.Map的某个实例中。

+1

这个答案(最后一部分)是正确的 - 通过使用像'HashMap :: ofAll(java.util.Map)'这样的方法'可以很容易地将任何Java'Map'进入一个Java程序。 –

3

虽然answer that Eugene提供的一般是真实的:有人必须做一个自定义收藏家。

但是,这并不一定是你的:Javaslang人已经为你处理它,通过提供在最简单的情况下工作的具体实现的Java地图的必要方法。例如,在Javaslang HashMap

javaslang.collection.HashMap::collector()

公共静态< K,V>集电极< Tuple2 < K,V>,ArrayList的< Tuple2 < K,V >>,HashMap中< K,V> > collector()

返回一个收集器,它可以和Stream.collect(java.util.stream.Collector)一起使用来获得一个HashMap。

类型参数

的K - 密钥类型

V - 是值类型

返回

一个HashMap收藏家。

编辑: 但是,它看起来并不像那必然工作,因为从收集的签名判断它:

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

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

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

返回一个HashMap,从源java.util.Map。没有预选赛,你可以在java.util.stream.Collectors找到

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

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

所有方法:

我们可以对你有什么类似这样的顶部添加此方法。

这段代码将收集到正常的Java Map,并且最后一步将调用Collector的Finisher,它会将所有来自Java Map的值放入Javalang map。

注意:我没有安装Java教程,也无法测试上面的代码片段编译,但它看起来像它做你想做的。

+0

我一直在看这个,但为了让它起作用,你是否必须将当前流转换为'Tuple2'?并已经计算出了数值? – Ash

+1

哦,对不起,我想我搞砸了一点。从收集器签名看来,它看起来像将“Tuple2”收集到一个“ArrayList”中,然后将所有这些添加到“HashMap”中。这不适合你,但我们可以通过使用其他内置方法来模仿这种行为。我会保留最初的版本,但会更新我的代码版本。 –

+1

@Ash,这个新的变体会为你工作吗?你需要更多关于它的信息吗? –

相关问题