Java 8+;使用Lambda或Stream从单例对象解包原语?Java中的结构化绑定?

Java 8+;使用Lambda或Stream从单例对象解包原语?Java中的结构化绑定?,java,lambda,java-stream,structured-bindings,Java,Lambda,Java Stream,Structured Bindings,实际上,我需要从函数返回中提取一部分数据,但实际上我并不需要返回的对象。那么,有没有一种方法可以简单地使用流或类似Lambda的语法获取我需要的内容?是的,我知道您可以使用stream().map()将值放入数组,然后将数组分解为命名变量,但对于功能等效的代码来说,这更为冗长 在C++中,这将被称为结构化绑定,但是当我搜索时,我好像缺少了它的java术语。 我似乎被迫编写程序代码: HandMadeTuple<Integer, Integer, ...> result = metho

实际上,我需要从函数返回中提取一部分数据,但实际上我并不需要返回的对象。那么,有没有一种方法可以简单地使用流或类似Lambda的语法获取我需要的内容?是的,我知道您可以使用stream().map()将值放入数组,然后将数组分解为命名变量,但对于功能等效的代码来说,这更为冗长

<>在C++中,这将被称为结构化绑定,但是当我搜索时,我好像缺少了它的java术语。

我似乎被迫编写程序代码:

HandMadeTuple<Integer, Integer, ...> result = methodICurrentlyCall(input);
int thing1 = result.getFirst();
int thing2 = result.getSecond();
...
//thingX's get used for various purposes. Result is never used again.
int thing1, thing2;
(methodICurrentlyCall(input)) -> (MyType mt) { thing1 = mt.getFirst(); thing2 = mt.getSecond(); };


有一个非常棘手的问题:数组

final int[] thing1 = {0}, thing2 = {0};
Stream.of(methodICurrentlyCall(input))
  .forEach(mt -> {
    thing1[0] = mt.getFirst();
    thing2[0] = mt.getSecond();
  });
数组引用是最终的,因此可以在lambdas中使用它

我不推荐这个它既不短也不容易理解

(另一个选项是使用
AtomicReference
AtomicInteger
/
AtomicLong
代替数组,但保证原子更新的开销最小)



如果您正在寻找对Java的模式匹配或解构支持,这可能会在Java的未来版本中实现,请参见以下相关问题:(更多详细信息请参见)

您的方法在Java中不受欢迎。lambda中使用的局部变量必须是final或有效final。这意味着变量thing1和thing2不能在lambda中更改。最好使用流的映射功能。@Ansarozeden stream().map()也不这样做。它所做的只是输出一个值。我可以收集列表中的值,但这比没用还糟糕。我理解“lambda中使用的局部变量必须是final或有效final”,但我有一个用例,该约束不利于生成更简洁、可读的代码。Java语言中是否存在一个桥梁,或者这只是一个不幸的缺口?如果我没有弄错你的问题,这其实不是关于流,而是关于一种目前不受Java支持但计划未来使用的语言结构。@Holger我补充了一些说明。我相信你是对的,这是一个解决方案,但我不一定把解决方案的形式限制在这个范围内。为什么我不能给一个内联函数一个方法调用的复杂/对象结果来解压原语呢?有一个基本原则,Java不允许创建对局部变量的引用,这些引用的持续时间可能比变量本身更长。您可以(有效地)引用最终变量,因为这可以通过复制值来实现,而不会牺牲一致性。但不能使用lambda表达式来指定外部作用域的局部变量。您可以做的最接近的事情是在相同的lambda表达式中正确使用变量,例如,
map.for((key,value)->/*使用key和value*/)。虽然这个例子是
void
,但类似的方法可能有一个(单一)结果。虽然原子整数的答案让我恼火,但它是可以接受的。我可以在评论中写道“Java中的缺陷要求lambdas具有函数式编程质量,不允许使用普通原语(从J8开始)。”如果Oracle的任何人或Java世界中的其他影响者看到了这一点,请修复您的语言,让人们编写合理的代码,看在上帝的份上。@patrickjp93那么不要用Java进行函数式编程。我不会到处抱怨Haskell让副作用编程变得如此困难,“应该清理它的行为”。不同的语言是以不同的模式构建的,我仍然不明白为什么
inta,b;提取(result->{a=result.a;b=result.b;})
var result=call()更可取;INTA=结果a,b=结果b——后者写起来更短,更容易理解;前者是复杂的,并且与临时依赖项有着内在的副作用(您无法知道lambda主体何时将被执行,也许它只是被惰性地评估?)我只想写一个类似的注释,
var mt=call();int a=mt.a,b=mt.b是我们进行比较的基线。替代方案更简单吗?不。它能让我们免于处理我们不感兴趣的物体吗?不,我们现在正在处理更多的对象,实际上我们对它们不感兴趣。我在前面的评论中所指的是“具有时间依赖性”(不是临时的):)
final int[] thing1 = {0}, thing2 = {0};
Stream.of(methodICurrentlyCall(input))
  .forEach(mt -> {
    thing1[0] = mt.getFirst();
    thing2[0] = mt.getSecond();
  });