我曾经在Scala中进行编程,但是我必须编写一些Java,并且试图执行与以下Scala代码段相同的功能:
trait Options[K, V] {
def add(key: K , value: V): Options[K, V]
}
val options: Options[T, U] = ???
val elems: List[(T, U)] = ???
elems.foldLeft(options) {
case (opts, (key, value)) => opts.add(key, value)
}
也就是说,我将elems
内options
上的元素折叠起来,并在每个步骤中生成一个新实例。
我尝试使用Java的Stream#reduce
:
interface Options<K, V> {
Options<K, V> add(K key, V value);
}
Options<K, V> options = ???
Stream<Tuple2<K, V>> elems = ??? // This is Reactor's Tuple2
elems.reduce(options, (opts, opt) -> opts.add(opt), ???)
我不知道组合器应该是什么,并且我在想象其参数将具有什么值时遇到了麻烦。我的理解是combiner
将用于合并并行流中并行产生的中间值。在我的情况下,我根本不关心并行处理elems
。换句话说,我正在寻找Flux#reduce
的同步和顺序版本。
我无法控制Options
的API。 elems
不必是Stream
。
答案 0 :(得分:3)
无法使用您提供的接口编写组合器。问题是组合器需要一种将两个Options
组合在一起的方法,但是没有办法做到。任何人对Options
实例唯一能做的就是在其中添加一对。我无法获得任何信息。大概做不到任何有用的事情。
也许此问题源于Java不具有特征且Java接口都不适合替代特征的事实。
惯用的Java编写方式只是沼泽标准的for循环:
Options<String, String> options = /*whatever*/;
List<Pair<String, String>> elems = /*whatever*/;
for (Pair<String, String> pair : elems)
{
options = options.add(pair.getKey(), pair.getValue());
}
如果您可以处理永远无法使用并行流的事实,则可以利用顺序流永远不会实际使用组合器这一事实。这样,您可以编写一个Collector
来定义一个将抛出异常的组合器。
Options<String, String> foo = elems.stream()
.collect(
() -> options,
(opt, pair) -> opt.add(pair.getKey(), pair.getValue()),
(a, b) -> { throw new UnsupportedOperationException(); }
);
如果您确实要使用reduce
,则需要修改您的界面以公开有关其包含的键值对的某些信息,或者提供一种添加多个键值对的方法立刻。例如:
interface Options<K, V>
{
Options<K, V> add(K key, V value);
Options<K, V> add(Options<K, V> otherOptions);
}
Options<String, String> options = /*whatever*/;
List<Pair<String, String>> elems = /*whatever*/;
Options<String, String> foo = elems.stream()
.reduce(
options,
(opt, pair) -> opt.add(pair.getKey(), pair.getValue()),
Options::add
);
我怀疑那是您想听到的,但是Scala和Java是不同的语言。您不应该期望所有东西都具有完全相同的东西。如果确实如此,那么就没有理由同时存在两种语言。