我在一个小库上工作,该库模拟流中的多价返回值。为此,我希望能够使用StreamTuple::new
而不是StreamTuple::create
或id -> new StreamTuple<>(id, id)
。我尝试了各种修改,但是我的通用fu还不够好,无法弄清楚如何更改源以允许。
public class StreamTuple<L, R> {
protected final L left;
protected final R right;
public StreamTuple(L left, R right) {
this.left = left;
this.right = right;
}
/**
* Suitable for method::references. Value is set to id.
*/
public static <L> StreamTuple<L, L> create(L left) {
return new StreamTuple<>(left, left);
}
....
调用代码段:
Map<String, String> m = Stream.of("1", "2", "3")
// .map(StreamTuple::create)
.map(id -> new StreamTuple<>(id, id))
.collect(toMap(StreamTuple::left, StreamTuple::right));
建议?还是无法完成?
编辑:我想要一个仅采用一个参数并返回流tuple的额外构造函数,其中l和r是相同的类型。当前的代码不能反映这一点,因为它是前一段时间,我无法使它起作用,我认为我已经复制了它。我只能找出如何提供L/R之一,这使另一个打开。如何为此编写单个参数构造函数?
您是否考虑过扩展StreamTuple
以定义单个参数构造函数?
Map<String, String> m = Stream.of("1", "2", "3")
.map( UnaryStreamTuple<String>::new )
.collect( Collectors.toMap(UnaryStreamTuple::left, UnaryStreamTuple::right) );
public class UnaryStreamTuple<T> extends StreamTuple<T, T> {
public UnaryStreamTuple(T left) {
super(left, left);
}
public UnaryStreamTuple(T left, T right) {
super(left, right);
}
}
无法使用构造函数来执行此操作,因为没有办法指定参数是L
和R
的子类型(即conjunction/controction/dutrosection(。该语言具有用于此要求的构造,但是不允许使用类型变量之间的相交:
// not allowed (causes a compilation error)
// vvvvv
public <LR extends L & R> StreamTuple(LR val) {
this.left = val;
this.right = val;
}
可能会在未来版本的Java中起作用。
您必须使用工厂方法,或者我想是Tsolakp建议的。我认为工厂更有意义。
流的 map
方法需要一个 Function
,它准确接收一个参数并返回其他内容。
但是,您尝试使用的是 StreamTuple::new
,其中2个参数,例如。 BiFunction
,所以不匹配。
我想您可以使用flatMap
具有每个流元素的两个副本,然后编写一个自定义的Collector
来一次收集这些项目2,但这听起来比引用已经匹配的create
方法要多得多。
最有效的是您所做的 - 一种恰好采用一个参数并返回所需StreamTuple
的工厂方法。
这是由于您两次传递id
,因此无法完成。StreamTuple::create
是要走的方式。
StramTuple::new
将根据接受方法预期的函数接口进行不同的翻译。
期望功能(t-> r(==> :: new转换为 new StreamTuple(t)
期望双方函数(t,u-> r(==> :: new转换为 new StreamTuple(t,u)
期望供应商((( -> r(==> :: new转换为 new StreamTuple()
由于流#映射正在期待一个函数,因此无法转换为2-args构造函数。因此,您的create
工厂方法似乎是一个不错的方法。
具有1-arg的配置器(如下(表现得像create
方法是不可能的
public StreamTuple(L both) { //will fail compilation
this.left = both;
this.right = both;
}
但是,由于您想要一个1-arg构造函数,其参数必须分配给R和L,因此您有2个选项:1(一个延伸另一个(例如R分配给L(
public class StreamTuple<L, R extends L> {
protected final L left;
protected final R right;
public StreamTuple(R both) {
this.left = both;
this.right = both;
}
}
2(如果r和l无关,则需要在getter上进行铸件的对象:
public class StreamTuple<L, R> {
protected final Object left, right;
public StreamTuple(Object o) {
this.left = this.right = o;
}
public <L> L getLeft() { return (L) left; }
public <R> R getRight() { return (R) right; }
}