Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
关闭不可变变量并将值作为lambda表达式在多个迭代中累积-Java 8_Java_Lambda_Java 8_Immutability - Fatal编程技术网

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

关闭不可变变量并将值作为lambda表达式在多个迭代中累积-Java 8,java,lambda,java-8,immutability,Java,Lambda,Java 8,Immutability,Jersey客户端中的WebTarget是作为不可变对象实现的,任何更改状态的操作都会返回一个新的WebTarget。要向其中添加查询参数(作为Map输入),编写了以下代码 public WebTarget webTarget(String path, Map<String, String> queryMap) { WebTarget webTarget = client.target(this.address.getUrl()).path(path); if (q

Jersey客户端中的WebTarget是作为不可变对象实现的,任何更改状态的操作都会返回一个新的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;
 }
publicWebTargetWebTarget(字符串路径,映射查询映射){
WebTarget WebTarget=client.target(this.address.getUrl()).path(path);
if(queryMap!=null)
forEach(e->webTarget.queryParam(e.getKey(),e.getValue());
返回webTarget;
}
这里的问题是每次调用
.queryParam()
都会返回一个新的WebTarget,我一直在思考如何累积,因为lambda表达式中使用的变量必须是final或隐式final,而不需要任何重新分配

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

用于尝试和利用原生Java8API中缺少的foldLeft,但由于WebTargetAPI缺乏对它的支持,它仍然处于谷底


EDIT2:foldLeft是下面答案中建议的方法,你可以在上面写一个小的

你可以使用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<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();
AtomicReference webTarget=新的AtomicReference(client.target(this.address.getUrl()).path(path));
if(queryMap!=null){
查询映射forEach((k,v)->{
updateAndGet(w->w.queryParam(k,v));
});
}
返回webTarget.get();

如果您想要功能性方法,您需要折叠(右)或缩小

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

功能Java:

<B> B foldLeft(final F<B, F<A, B>> bff, final B z)

WebTarget wt = wtCollection.foldLeft(x -> (y -> x.queryParam(...)), new WebTarget());

猜一猜像foldLeft这样的带有零值的WebTarget,它携带状态,尽管迭代可能会有所帮助!!!我们是否有一种使用java-8执行foldLeft的机制看看除了
forEach
之外的其他API方法。另一个好的起点是。使用普通循环<代码>for(条目e:queryMap)webTarget=webTarget.queryParam(…)在我看来很好…对不起,我正在寻找一种正确的方法。似乎用对方付费的方式会很好地完成这项工作。对方付费似乎不是最好的。我想说一个普通的循环是最合适的。另外,当后来有人说“嘿,我可以并行运行这个流”时,你的代码会被微妙地破坏,可能会在没有任何警告的情况下给出错误的答案。好把戏!你真的在那个愚蠢的编译器上加了一个。使用
reduce
,这就是它的目的。@Holger在任何情况下,一个arg数组的技巧都是不合理的——正如第一位评论员所指出的,有数百万开发人员愿意利用这个“聪明”的技巧来“愚弄”编译器,在这个过程中胜过他们自己和他们的维护人员。(如果你要这样做,至少使用一个AtomicRef。)所以我的评论更像是“永远不要这样做”,而不是对特定代码的评论。@matt:或者,你写
queryMap.forEach((k,v)->{webTarget.updateAndGet(w->w.queryParam(k,v));})(注意
结尾),或者您编写
queryMap.forEach((k,v)->webTarget.updateAndGet(w->w.queryParam(k,v));
(不带花括号)。您现在编写的方式是无效语法。如果我理解正确,streamx解决方案应该类似于:
webTarget=streamx.of(queryMap.entrySet().stream()).foldLeft(webTarget,(w,e)->w.queryParam(e.getKey(),e.getValue());
如果(queryMap!=null){…}
分支,则必须将其放入
中。有趣的技术,谢谢!
<U> U foldLeft(U seed, BiFunction<U, ? super T, U> accumulator) 
queryMap.entrySet().stream()
    .reduce(new WebTarget(), (x, y) -> { 
        x.queryParam(y.getKey(), y.getValue()); 
    });