关闭不可变变量并将多次迭代中的值累加为 lambda 表达式 - Java 8
Closing over immutable variable and accumulate values across multiple iterations as a lambda expression - Java 8
Jersey 客户端中的 WebTarget 被实现为一个不可变对象,任何改变状态的操作 returns 一个新的 WebTarget。要向其添加查询参数,它以 Map<>
的形式出现,编写了以下代码。
public WebTarget webTarget(String path, Map<String, String> queryMap) {
WebTarget webTarget = client.target(this.address.getUrl()).path(path);
if (queryMap != null)
queryMap.entrySet().forEach(e -> webTarget.queryParam(e.getKey(), e.getValue()));
return webTarget;
}
这里的问题是每次调用 .queryParam()
returns 一个新的 WebTarget 并且我被困在如何累加的问题上,因为在 lambda 表达式中使用的变量必须是 final 或隐式 final , 没有任何重新分配。
编辑:
在这种情况下,减少可能不是一个选项,因为 WebTarget 缺乏减少机制,我无法从一个 webtarget 获取 queryParam 并将其设置到另一个。如果 WebTarget api 对累积有更好的支持,就可以使用它。
使用 Jool 尝试利用原生 Java 8 API 中缺少的 foldLeft,但由于 WebTarget api 缺乏对它的支持,它仍然触底.
EDIT2:foldLeft 是下面答案中建议的方式,在这个
上写了一个小 blog
您可以使用 ol' 数组技巧,它除了概念验证外没有任何用处。
WebTarget[] webTarget = {client.target(this.address.getUrl()).path(path)};
if (queryMap != null){
queryMap.forEach((k, v)->{
webTarget[0] = webTarget[0].queryParam(k, v);
});
}
return webTarget[0];
您可以使用 AtomicReference 对其进行改进。
AtomicReference<WebTarget> webTarget = new AtomicReference<>(client.target(this.address.getUrl()).path(path));
if (queryMap != null){
queryMap.forEach((k, v)->{
webTarget.updateAndGet(w->w.queryParam(k, v));
});
}
return webTarget.get();
如果你想要函数式方法,你需要 foldLeft(right) 或 reduce。
foldLeft
在某些库中实现,例如 Functionaljava and streamEx.
功能java:
<B> B foldLeft(final F<B, F<A, B>> bff, final B z)
WebTarget wt = wtCollection.foldLeft(x -> (y -> x.queryParam(...)), new WebTarget());
StreamEx:
<U> U foldLeft(U seed, BiFunction<U, ? super T, U> accumulator)
UPD
流减少
queryMap.entrySet().stream()
.reduce(new WebTarget(), (x, y) -> {
x.queryParam(y.getKey(), y.getValue());
});
Jersey 客户端中的 WebTarget 被实现为一个不可变对象,任何改变状态的操作 returns 一个新的 WebTarget。要向其添加查询参数,它以 Map<>
的形式出现,编写了以下代码。
public WebTarget webTarget(String path, Map<String, String> queryMap) {
WebTarget webTarget = client.target(this.address.getUrl()).path(path);
if (queryMap != null)
queryMap.entrySet().forEach(e -> webTarget.queryParam(e.getKey(), e.getValue()));
return webTarget;
}
这里的问题是每次调用 .queryParam()
returns 一个新的 WebTarget 并且我被困在如何累加的问题上,因为在 lambda 表达式中使用的变量必须是 final 或隐式 final , 没有任何重新分配。
编辑: 在这种情况下,减少可能不是一个选项,因为 WebTarget 缺乏减少机制,我无法从一个 webtarget 获取 queryParam 并将其设置到另一个。如果 WebTarget api 对累积有更好的支持,就可以使用它。
使用 Jool 尝试利用原生 Java 8 API 中缺少的 foldLeft,但由于 WebTarget api 缺乏对它的支持,它仍然触底.
EDIT2:foldLeft 是下面答案中建议的方式,在这个
上写了一个小 blog您可以使用 ol' 数组技巧,它除了概念验证外没有任何用处。
WebTarget[] webTarget = {client.target(this.address.getUrl()).path(path)};
if (queryMap != null){
queryMap.forEach((k, v)->{
webTarget[0] = webTarget[0].queryParam(k, v);
});
}
return webTarget[0];
您可以使用 AtomicReference 对其进行改进。
AtomicReference<WebTarget> webTarget = new AtomicReference<>(client.target(this.address.getUrl()).path(path));
if (queryMap != null){
queryMap.forEach((k, v)->{
webTarget.updateAndGet(w->w.queryParam(k, v));
});
}
return webTarget.get();
如果你想要函数式方法,你需要 foldLeft(right) 或 reduce。
foldLeft
在某些库中实现,例如 Functionaljava and streamEx.
功能java:
<B> B foldLeft(final F<B, F<A, B>> bff, final B z)
WebTarget wt = wtCollection.foldLeft(x -> (y -> x.queryParam(...)), new WebTarget());
StreamEx:
<U> U foldLeft(U seed, BiFunction<U, ? super T, U> accumulator)
UPD 流减少
queryMap.entrySet().stream()
.reduce(new WebTarget(), (x, y) -> {
x.queryParam(y.getKey(), y.getValue());
});