带有附加信息的Java8计数采集器

带有附加信息的Java8计数采集器,java,java-8,collectors,Java,Java 8,Collectors,我使用Java8的计数收集器来获取有关值计数的信息 例如:; 如果我有一堆像这样的溪流 Stream<String> doc1 = Stream.of("a", "b", "c", "b", "c"); Stream<String> doc2 = Stream.of("b", "c", "d"); Stream<Stream<String>> docs = Stream.of(doc1, doc2); 但是,我希望将计数与它起源的docId相关联

我使用Java8的计数收集器来获取有关值计数的信息

例如:; 如果我有一堆像这样的溪流

Stream<String> doc1 = Stream.of("a", "b", "c", "b", "c");
Stream<String> doc2 = Stream.of("b", "c", "d");
Stream<Stream<String>> docs = Stream.of(doc1, doc2);
但是,我希望将计数与它起源的docId相关联。例如,我希望有一个结构作为

[
{a=1, b=2, c=2}, 
{b=1, c=1, d=1}
]
[
{a=(randId1, 1), b=(randId1, 2), c=(randId1, 2)}, 
{b=(randId2, 1), c=(randId2, 1), d=(randId2, 1)}
]
其中,
randId1
randId2
可以在运行时生成(我只需要一种追溯到唯一源的方法),并且
()
表示来自Apache的类

我试图将文档包装成一对
(docId,doc)
,但我一直在修改
收集器。counting()
替换

List<Map<String, Long>> collect = docs.map(doc -> Pair.of(UUID.randomUUID(), doc))
    .map(p -> p.getRight().collect(Collectors.groupingBy(Function.identity(), Collectors.counting())))
    .collect(Collectors.toList());
List collect=docs.map(doc->Pair.of(UUID.randomuid(),doc))
.map(p->p.getRight().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()))
.collect(Collectors.toList());

如何获得所需格式的输出?

这不是很可读。。。我已经用
AbstractMap.SimpleEntry
替换了
Pair
,因为它做同样的事情,而且我已经在我的类路径上有了它

 List<Map<String, AbstractMap.SimpleEntry<Long, UUID>>> result = docs.map(doc -> doc.collect(Collectors.collectingAndThen(
            Collectors.groupingBy(Function.identity(), Collectors.counting()),
            map -> {
                UUID rand = UUID.randomUUID();
                return map.entrySet().stream().collect(Collectors.toMap(
                        Entry::getKey,
                        e -> new AbstractMap.SimpleEntry<>(e.getValue(), rand)));
            })))
            .collect(Collectors.toList());

    System.out.println(result);

我想你可以这样做:

List<Map<String, Pair<UUID, Long>>> result = docs
    .map(doc -> Pair.of(UUID.randomUUID(), doc))
    .map(p -> p.getRight() // right: doc stream
        .map(word -> Pair.of(word, p.getLeft()))) // left: uuid
    .map(stream -> stream.collect(Collectors.toMap(
        Pair::getLeft, // word
        p -> Pair.of(p.getRight(), 1L), // right: uuid
        (p1, p2) -> Pair.of(p1.getLeft(), p1.getRight() + p2.getRight())))) // merge
    .collect(Collectors.toList());
也许可以通过将收集内部流的代码移动到助手方法来改进这一点:

private Map<String, Pair<UUID, Long>> collectInnerDoc(
        Stream<Pair<String, UUID>> stream) {
    return stream.collect(Collectors.toMap(
        Pair::getLeft, // word
        p -> Pair.of(p.getRight(), 1L), // random doc id
        (p1, p2) -> Pair.of(p1.getLeft(), p1.getRight() + p2.getRight()))); // merge
}
private-Map-doc(
(溪流){
返回流.collect(Collectors.toMap(
Pair::getLeft,//word
p->Pair.of(p.getRight(),1L),//随机文档id
(p1,p2)->Pair.of(p1.getLeft(),p1.getRight()+p2.getRight());//合并
}
然后,您可以使用此方法收集外部流:

List<Map<String, Pair<UUID, Long>>> result = docs
    .map(doc -> Pair.of(UUID.randomUUID(), doc))
    .map(p -> p.getRight() // right: doc stream
        .map(word -> Pair.of(word, p.getLeft()))) // left: uuid
    .map(this::collectInnerDoc) // map inner stream to map
    .collect(Collectors.toList());
列表结果=文档
.map(doc->Pair.of(UUID.randomUUID(),doc))
.map(p->p.getRight()//右:单据流
.map(word->Pair.of(word,p.getLeft())//left:uuid
.map(this::collectInnerDoc)//将内部流映射到映射
.collect(Collectors.toList());
这假设私有方法是在收集外部流的同一类中声明的。如果不是这种情况,请相应地更改
this::collectInnerDocs
方法引用。

这如何

List<Map<String, Pair<UUID, Long>>> collect = docs.map(doc -> {
    UUID id = UUID.randomUUID();
    return doc.collect(groupingBy(
        identity(),
    //  v--- adapting Collector<?,?,Long> to Collector<?,?,Pair>    
        collectingAndThen(counting(), n -> Pair.of(id, n))
    ));
}).collect(Collectors.toList());

回答得很好。。感谢you@Anoop一点也不。这是我的荣幸。这是几个伟大答案中的另一个。非常感谢你。
private Map<String, Pair<UUID, Long>> collectInnerDoc(
        Stream<Pair<String, UUID>> stream) {
    return stream.collect(Collectors.toMap(
        Pair::getLeft, // word
        p -> Pair.of(p.getRight(), 1L), // random doc id
        (p1, p2) -> Pair.of(p1.getLeft(), p1.getRight() + p2.getRight()))); // merge
}
List<Map<String, Pair<UUID, Long>>> result = docs
    .map(doc -> Pair.of(UUID.randomUUID(), doc))
    .map(p -> p.getRight() // right: doc stream
        .map(word -> Pair.of(word, p.getLeft()))) // left: uuid
    .map(this::collectInnerDoc) // map inner stream to map
    .collect(Collectors.toList());
List<Map<String, Pair<UUID, Long>>> collect = docs.map(doc -> {
    UUID id = UUID.randomUUID();
    return doc.collect(groupingBy(
        identity(),
    //  v--- adapting Collector<?,?,Long> to Collector<?,?,Pair>    
        collectingAndThen(counting(), n -> Pair.of(id, n))
    ));
}).collect(Collectors.toList());
              //  v--- the code need to edit is here
List<Map<String, Long>> collect = docs
.map(doc -> doc.collect(Collectors.groupingBy(Function.identity()
 //                    the code need to edit is here ---v
                                             ,Collectors.counting())))
.collect(Collectors.toList());