简体   繁体   English

如何使用流和 lambda 表达式重写此方法?

[英]How can I rewrite this method using streams and lambda expressions?

I have this piece of code here that basically just creates a number of threads equal to the parameter, instantiates a MyRunnable object in each thread, adds the thread to a list of threads and then sets the name of the thread according to the iteration on the for loop.我这里有这段代码基本上只是创建了一些等于参数的线程,在每个线程中实例化一个 MyRunnable object,将线程添加到线程列表,然后根据迭代设置线程的名称循环。

public class ThreadManager {
    protected List<Thread> threads;

    public void createThreads(int number) {
        
        for (int i = 0; i < number; i++) {
            Thread thread = new Thread(MyRunnable::new);
            threads.add(thread);
            thread.setName("thread"+i);
        }
    }
}

My question is if there's a cleaner way to do this?我的问题是是否有更清洁的方法来做到这一点? Is it possible to encapsulate this functionality in a lambda with the use of streams?是否可以使用流将此功能封装在 lambda 中?

Lambdas are non-transparent in regards to mutable local variables, control flow, and checked exceptions. Lambda 在可变局部变量、控制流和检查异常方面是不透明的。

That's really bad... if the lambdas are guaranteed to run 'as you use them'.那真的很糟糕……如果保证 lambda 表达式“在您使用它们时”运行。 It's great if you are handing the lambdas off to other threads or contexts to run at completely different times.如果您将 lambda 传递给其他线程或上下文以在完全不同的时间运行,那就太好了。 That explains why lambdas aren't transparent in those 3 regards: That's fantastic if the lambda runs out-of-context which they are designed to be capable of doing.这解释了为什么lambda 在这 3 个方面不透明:如果 lambda 在它们被设计为能够执行的上下文之外运行,那就太棒了。

As a consequence, when the job you're using them for is guaranteed to run in context, lambdas bad.因此,当你使用它们的工作保证在上下文中运行时,lambdas 很糟糕。 Sometimes they are the lesser evil, in which case its still worthwhile to run them, but, all other things being equal?有时它们是较小的邪恶,在这种情况下仍然值得运行它们,但是,所有其他条件都相同吗? Lambda bad. Lambda 坏了。

So, why would you possibly be interested in writing this extremely simple code to lambdas?那么,为什么您可能会对将这个极其简单的代码编写为 lambda 感兴趣? You'd just be making matters worse.你只会让事情变得更糟。

but, if you want to ignore all that, reduce your toolbox to just a hammer (lambdas/stream API), and thus use it for everything, even things hammers weren't really designed for:但是,如果你想忽略所有这些,将你的工具箱缩减为一个锤子(lambdas/stream API),然后将它用于所有事情,即使锤子并不是真正设计用于:

threads = IntStream.of(0, number)
  .mapToObj(i -> new Thread(new MyRunnable(), "thread" + i))
  .toList();

Note that you wrote MyRunnable::new which isn't what you want.请注意,您编写MyRunnable::new不是您想要的。

MyRunnable::new constructs an entirely new class (not your MyRunnable!) that implements Runnable and whose run() method does: MyRunnable::new构造了一个全新的class (不是你的MyRunnable!),它实现了 Runnable 并且其run()方法执行以下操作:

  • Create a new instance of MyRunnable.创建 MyRunnable 的新实例。
  • Toss it in the garbage.把它扔进垃圾桶。
  • Return.返回。

I rather doubt you wanted that.我很怀疑你想要那个。 Just new MyRunnable() will.. make a new myrunnable.只是new MyRunnable()将..创建一个新的 myrunnable。 Which is what you want, no?哪个是你想要的,不是吗?

I'd just do this instead:我只是这样做:

for (int i = 0; i < number; i++) {
  list.add(new Thread(new MyRunnable(), "thread" + i));
}

Shorter, simpler to understand, more flexible for future changes (example: If ever you change things up and you throw some checked exceptions from inside there, that's no problem. Whereas with the lambda form you'd have to toss it in the bin and start over. Or even: You want to log something in addition to making a new thread object - in the lambda version you need to add braces and in general go to town on the structure. Whereas with the second snippet, just... add a log statement. No other changes required at all).更短,更容易理解,对未来的变化更灵活(例如:如果你改变了一些东西并且你从那里抛出一些检查过的异常,那没问题。而对于 lambda 表格你必须把它扔进垃圾箱并且重新开始。甚至:除了创建新线程 object 之外,您还想记录一些内容 - 在 lambda 版本中,您需要添加大括号,通常 go 到结构上的城镇。而对于第二个片段,只需...添加日志语句。根本不需要其他更改)。

You can do it like this:你可以这样做:

public class ThreadManager {

  protected List<Thread> threads;

  public void createThreads(int number) {
    IntStream.range(0, number).forEach(i -> threads.add(new Thread(MyRunnable::new, "thread" + i)));
  }
}

IntStream.range() creates stream, which will behave like your loop. IntStream.range()创建 stream,其行为类似于您的循环。 To cite - Returns a sequential ordered IntStream from startInclusive (inclusive) to endExclusive (exclusive) by an incremental step of 1. .引用 - Returns a sequential ordered IntStream from startInclusive (inclusive) to endExclusive (exclusive) by an incremental step of 1. .. The code certainly is shorter, but i highly doubt it will be cleaner.代码当然更短,但我非常怀疑它会更干净。

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

相关问题 如何使用java 8 lambda表达式迭代两个流并保持计数 - How do I iterate through two streams using java 8 lambda expressions and keeping a count 我们如何在没有 lambda 表达式和流的情况下转换以下代码? - How can we convert below code without lambda expressions and streams? 如何使用 Lambda 和 Streams 反转 Java 8 中的单个字符串? - How can I reverse a single String in Java 8 using Lambda and Streams? 如何将此代码更改为流和 lambda 表达式 - how to change this code to streams and lambda expressions 如何在Java中使用Lambda表达式 - How can I use Lambda Expressions in Java StringBuilder 到 Streams 和 Lambda 表达式 - StringBuilder to Streams and Lambda expressions 使用java 8流处理null属性并使用lambda表达式进行排序 - Dealing with a null attribute using java 8 streams and sorting using lambda expressions 如何删除用作侦听器的lambda表达式/方法句柄? - How do I remove lambda expressions/method handles that are used as listeners? 使用流和 lambda 表达式替换嵌套的 for 循环以进入嵌套列表 - Using streams and lambda expressions to replace a nested for loop to enter into a nested list 如何在带有lambda表达式的java 8中使用多个流和.map函数 - How to use multiple streams and .map functions in java 8 with lambda expressions
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM