关闭不可变变量并在多个迭代中累积值作为lambda表达式 – Java 8

Jersey客户端中的WebTarget是作为不可变对象实现的,任何更改状态的操作都会返回一个新的WebTarget。 要向其中添加查询参数(以Map出现),编写了以下代码。

 public WebTarget webTarget(String path, Map 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()返回一个新的WebTarget,而我仍然坚持如何累积,因为lambda表达式中使用的变量必须是final或implicit final,而不需要任何重新分配。

编辑 :在这种情况下,Reduce可能不是一个选项,因为WebTarget缺少减少机制,我无法从一个webtarget获取queryParam并将其设置为另一个。 如果WebTarget api有更好的支持积累,它本可以使用。

使用Jool来尝试利用本地Java 8 API中缺少的foldLeft,但由于WebTarget api缺乏对它的支持,它仍然处于最低点。

EDIT2 :foldLeft是下面的答案所建议的方式,写了一个小博客

如果你想要function性方法,你需要foldLeft(右)或减少。

foldLeft在一些库中实现,例如Functionaljava和streamEx 。

Functionaljava:

  B foldLeft(final F> bff, final B z) WebTarget wt = wtCollection.foldLeft(x -> (y -> x.queryParam(...)), new WebTarget()); 

StreamEx:

  U foldLeft(U seed, BiFunction accumulator) 

UPD流 – 减少

 queryMap.entrySet().stream() .reduce(new WebTarget(), (x, y) -> { x.queryParam(y.getKey(), y.getValue()); }); 

你可以使用ol’数组技巧,这不仅仅是一个概念validation的好处。

 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 = 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();