简体   繁体   English

将 For 循环转换为 Java 中的 lambda 表达式

[英]Convert a For loop to a lambda expression in Java

I have the following code我有以下代码

//assume we have a list of custom type "details" already constructed 

 for(int i = 0; i < details.size(); ++i) {
    CallerID number = details.get(i).getNextNumber();
    ClientData.addToClient(number);
                
 }

I have oversimplified the code.我过度简化了代码。 The enum CallerID and the ClientData object work as intended.枚举 CallerID 和 ClientData object 按预期工作。 I am asking for help converting this loop to a lambda function so I can understand the logic of how to do so, then fill in the appropriate code as needed.我请求帮助将此循环转换为 lambda function 以便我可以理解如何执行此操作的逻辑,然后根据需要填写适当的代码。

Let's first write it as a modern basic for loop and golf it a bit, just so we're comparing apples to apples:让我们先把它写成一个现代的基础 for 循环然后稍微打高尔夫,这样我们就可以比较苹果和苹果了:

for (var detail : details) clientData.addToClient(detail.getNextNumber());

And this is probably the right answer.这可能是正确的答案。 It is local var, exception, and control flow transparent (which is what you want), and short.它是本地变量、异常和控制流透明(这是您想要的),而且很短。

The lambda form is this, but it's got downsides (mostly, those transparencies). lambda 形式就是这样,但它有缺点(主要是那些透明胶片)。 It also isn't any shorter.它也不短了。 You shouldn't write it this way.你不应该这样写。

details.stream().forEach(d -> clientData.addToClient(detail.getNextNumber());

You may be able to just remove stream() from that.您也许可以从中删除stream() But probably not.但可能不是。

Generally when people say "I want it in lambda form", that's not because someone is holding a gun to your head - you are saying that because somebody peddling a religion of sorts to you told you that 'it was better' and that this 'will scale'.一般来说,当人们说“我想要 lambda 形式的”时,这并不是因为有人拿着枪指着你的头——你是在说,因为有人向你兜售某种宗教,告诉你'它更好',而这'将扩展'。 Realize that they are full of it.意识到他们充满了它。 There can be advantages to 'functional style', but none of these snippets are functional . “功能风格”可能有优势,但这些片段都不是功能性的 A true functional style would involve a bunch of side-effect-free transformations, and then returning something.真正的函数式风格将涉及一堆无副作用的转换,然后返回一些东西。

.addToClient ? .addToClient You've lost the functional game there - you would want to instead convert each detail to something (presumably a ClientID ), and from there construct an immutable object from that stream.您已经失去了那里的功能游戏 - 您希望将每个detail转换为某些东西(大概是ClientID ),然后从那里构造一个不可变的 object 从 stream 。 You'd 'collect' your ClientIDs into a clientData object.您将“收集”您的 ClientID 到clientData object 中。

Let's say for example that clientData is just a 'list of ClientIDs' and nothing more.例如, clientData只是一个“ClientID 列表”,仅此而已。 Then you'd write something like this:然后你会写这样的东西:

var clientData = details.stream()
  .map(MyDetailClass::getNextNumber)
  .collect(Collectors.toList());

Is this better ?更好吗? No. However, if you're looking for 'a stream-style, lambda-based functional take on things', that qualifies.不,但是,如果您正在寻找“一种流式、基于 lambda 的函数式处理方式”,那就符合条件了。 The output is constructed by way of collection (and not forEach that does a side-effect operation), and all elements involved are (or can be) immutable. output 是通过集合(而不是forEach执行副作用操作)的方式构造的,并且所有涉及的元素都是(或可以是)不可变的。

There's no particular reason why you'd want this, but if for some reason you're convinced this is better, now you know what you want to do.没有什么特别的理由让你想要这个,但如果出于某种原因你确信这会更好,那么现在你知道你想做什么了。 "Just replace it with a lambda" doesn't make it 'functional'. “只需用 lambda 替换它”并不能使其“功能化”。

I am asking for help converting this loop to a lambda function so I can understand the logic of how to do so, then fill in the appropriate code as needed.我请求帮助将此循环转换为 lambda function 以便我可以理解如何执行此操作的逻辑,然后根据需要填写适当的代码。

A Function returns a value. Function返回一个值。 As you are just updating something what you need is a Consumer which accepts a single argument of a list of some detail.当您只是在更新某些东西时,您需要的是一个Consumer ,它接受一些细节列表的单个参数。 Assuming those are in a Class named SomeDetails , here is how you would do it.假设它们位于名为ClassSomeDetails中,您将按照以下方式进行操作。

As you iterating over some structure limited by size and using get(i) I am presuming a list is required here.当您迭代一些受size限制的结构并使用get(i)时,我假设这里需要一个列表。

List<SomeDetails> details = new ArrayList<>(); // then populated

// lambda definition
Consumer<List<SomeDetails>> update = (lst)-> {
            for(SomeDetails detail : lst) {
                  CallerID number = detail.getNextNumber();
                  ClientData.addToClient(number);
            }
};

And then invoke it like this, passing the List.然后像这样调用它,传递列表。

update.accept(details);

All the above does is encapsulate the for loop (using the enhanced version for simplicity) and perform the operation.以上所做的就是封装for循环(为简单起见使用增强版)并执行操作。

If this is all you wanted, I would recommend just doing it as you were doing it sans the lambda.如果这就是您想要的,我建议您在没有 lambda 的情况下这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM