Groovy注入没有类似的Java8Reduce
通常我认为Groovy的Groovy注入没有类似的Java8Reduce,groovy,java-8,Groovy,Java 8,通常我认为Groovy的inject方法相当于Java8的reduce,但我似乎遇到了一个不寻常的情况 假设我有一本名叫Book class Book { int id String name } 如果我有一个书籍集合,并希望将它们转换为一个映射,其中键是id,值是书籍,那么在Groovy中,编写以下代码非常简单: Map bookMap = books.inject([:]) { map, b -> map[b.id] = b map } i、 例如,
inject
方法相当于Java8的reduce
,但我似乎遇到了一个不寻常的情况
假设我有一本名叫Book
class Book {
int id
String name
}
如果我有一个书籍集合,并希望将它们转换为一个映射,其中键是id,值是书籍,那么在Groovy中,编写以下代码非常简单:
Map bookMap = books.inject([:]) { map, b ->
map[b.id] = b
map
}
i、 例如,对于每本书,将其添加到书id下的地图中,然后返回地图
在Java8中,相同的操作将采用完全不同的方法。或者:
Map<Integer, Book> bookMap = books.stream()
.collect(Collectors.toMap(Book::getId, b -> b));
不同之处在于风格
然而,我想知道的是,在Java8中是否有类似于Groovy的inject
的reduce
操作。我不能只是模仿我在Groovy中所做的,因为在Java 8中,reduce
的签名是:
T reduce(T identity, BinaryOperator<T> accumulator)
T reduce(T标识,二进制运算符累加器)
BinaryOperator
意味着lambda表达式的两个元素必须是相同的类型。如果它是一个双函数
,我可以将lambda的第一个参数设置为HashMap
,将第二个参数设置为Book
,但我不能使用二进制运算符
。我知道有一个三参数版本的reduce
,但这似乎也没有帮助
我错过了什么明显的东西吗?只是inject
比reduce
更通用吗?因为我已经有了一种用Java解决问题的惯用方法,这并不重要,但这里的差异让我印象深刻。yoken!:-D
您需要以下条件:
List<Book> books = Arrays.asList(
new Book(1, "Book One"),
new Book(2, "Tim's memoirs"),
new Book(3, "Harry Potter and the sarcastic cat")
);
第一个参数是要收集到的对象:
new HashMap<Integer, Book>(),
reduce调用中的第三个二进制运算符:
(a, b) -> {
a.putAll(b);
return a;
}
假设您正在运行并行流,则如何将所有生成的映射重新连接在一起
put
和putAll
returningvoid
让它变得一团糟:-(但我猜链接在90年代末不是一件流行的事情…这正是我所需要的。我仍然在纳闷为什么reduce方法是这样设计的(带有一个单独的累加器和合并器),而在Groovy中注入(像往常一样)简单多了,就这样吧。另外,我假设“HP和讽刺猫”中的讽刺猫可能是动物形态的麦格。组合器仅用于parallel()
streams…如果你在组合器中放入throw new RuntimeException(“boom”)
,你会看到正常流没有被调用。。。
{
1=Book{id=1, name='Book One'},
2=Book{id=2, name='Tim's memoirs'},
3=Book{id=3, name='Harry Potter and the sarcastic cat'}
}
new HashMap<Integer, Book>(),
(map, value) -> {
map.put(value.id, value);
return map;
},
(a, b) -> {
a.putAll(b);
return a;
}