如何在Java8流/过滤器中使用非最终变量?
在我的用例中,我想更新一个变量的值,并在streams的下一次迭代中引用它 但是java编译器给了我一个错误。这是我的密码如何在Java8流/过滤器中使用非最终变量?,java,java-8,java-stream,Java,Java 8,Java Stream,在我的用例中,我想更新一个变量的值,并在streams的下一次迭代中引用它 但是java编译器给了我一个错误。这是我的密码 static String convertList( List<Map.Entry<String, String>> map, String delimiter, long maxLength ) { long currentLength
static String convertList(
List<Map.Entry<String, String>> map,
String delimiter,
long maxLength
) {
long currentLength = 0L;
return map.stream()
.map(e->e.getKey() + "=" + e.getValue())
.filter(p->{
long pLength = p.getBytes(StandardCharsets.UTF_8).length;
currentLength = currentLength + pLength;
if (currentLength <= maxLength) {
return true;
} else {
return false;
}
})
.collect(Collectors.joining(delimiter));
}
静态字符串转换列表(
列表地图,
字符串分隔符,
长最大长度
) {
长电流长度=0L;
返回map.stream()
.map(e->e.getKey()+“=”+e.getValue())
.filter(p->{
long pLength=p.getBytes(StandardCharsets.UTF_8).length;
电流长度=电流长度+正压;
如果(currentLength您的变量必须是final/effective final才能在lambda中使用它。您仍然可以通过使用像数组这样的最终“容器对象”来实现您的目标-特别是在您的示例中,long[1]
或AtomicLong
可以很好地工作-引用是最终的,但您可以更改内容
基于您的代码的示例:
final long[] currentLength = new long[1];
return map.stream()
.map(e->e.getKey() + "=" + e.getValue())
.filter(p->{
long pLength = p.getBytes(StandardCharsets.UTF_8).length;
currentLength[0] = currentLength[0] + pLength;
if (currentLength[0] + maxLength <= maxLength) {
return true;
} else {
return false;
}
}).collect(Collectors.joining(delimiter));
final long[]currentLength=新长[1];
返回map.stream()
.map(e->e.getKey()+“=”+e.getValue())
.filter(p->{
long pLength=p.getBytes(StandardCharsets.UTF_8).length;
currentLength[0]=currentLength[0]+正压;
如果(currentLength[0]+maxLength{
long pLength=p.getBytes(StandardCharsets.UTF_8).length;
currentLength[0]=currentLength[0]+正压;
return(currentLength[0]+maxLength一旦满足条件,您应该使用一个循环和break;
。它更快,因为它可以提前退出(流将遍历整个列表),并且不违反规范,该规范要求传递的谓词必须是无状态的
streamfilter(Predicate我不确定Stream
在执行有状态操作时是否是正确的工具,但无论如何,这里有一个解决方案可以工作,但看起来有点粗糙
private static String convertList(列表映射、字符串分隔符、long maxLength){
AtomicLong currentLength=新的AtomicLong();
返回map.stream()
.map(e->e.getKey()+“=”+e.getValue())
.peek(s->currentLength.addAndGet(s.getBytes(StandardCharsets.UTF_8.length))
.filter(p->currentLength.get())谢谢。它像一个符咒一样工作。我只是注意到我没有将分隔符计算到总大小。你有什么建议吗?我对Java8相当陌生。我不完全确定你的意思,但你的过滤条件看起来有点可疑-它几乎总是返回false(只有当currentLength
为0或负时,它才是真的,而且永远不会是负的)。很抱歉,这是一个错误。我更新了问题。检查为if(currentLength Collector在每次迭代时都会将分隔符连接到最终字符串。我想计算总大小限制的字节数。我也在寻找相同的字节数。您能给我一个解决此问题的示例代码吗?这将非常有帮助。不,我认为散文应该足够了,因为在任何情况下编写循环都是一项非常基本的任务编程语言和许多教程都涵盖了这一点。事实上,我应该在你最后的评论中否决你@the8472。因为这是一项非常“基本的任务”,你可以把它写下来。现在我必须再次在其他地方搜索该解决方案。这正是流的目的。顺便说一句,像if(currentLength)这样的语句
.filter(p->{
long pLength = p.getBytes(StandardCharsets.UTF_8).length;
currentLength[0] = currentLength[0] + pLength;
return (currentLength[0] + maxLength <= maxLength);
})
private static String convertList(List<Map.Entry<String, String>> map, String delimiter, long maxLength) {
AtomicLong currentLength = new AtomicLong();
return map.stream()
.map(e -> e.getKey() + "=" + e.getValue())
.peek(s -> currentLength.addAndGet(s.getBytes(StandardCharsets.UTF_8).length))
.filter(p -> currentLength.get() <= maxLength)
.collect(Collectors.joining(delimiter));
}