有人在接受采访时问我是否应该用主要方法编写流媒体操作。
这有什么不同吗?
例如:
class Athlete {
private String name;
private int id;
public Athlete(String name,int id) {
this.name = name;
this.id = id;
}
}
public class Trial {
public static void main(String[] args) {
List<Athlete> list = new ArrayList<>();
list.add(new Athlete("John", 1));
list.add(new Athlete("Jim", 2));
list.add(new Athlete("Jojo", 3));
list.stream().forEach(System.out::print); // or any other any stream operation
}
}
所以我很想知道它是否有任何区别......现在,我唯一知道的是,一旦消耗了流,它就不能再被消耗了。
它是否会影响内存或在JVM中创建用于流式传输的缓冲区内存?
如果是的话?为什么不在主方法中使用它?
答案 0 :(得分:4)
“我们应该在主方法中编写流操作”的问题是一个加载的问题。它暗示的第一件事是假设main
方法有一些特殊之处。无论我们在谈论哪些操作,如果结论是您可能会或可能不会以任意方法使用它们,那么当有问题的方法是main
时,您没有理由得出不同的结论。方法
显然,“我们应该......”实际上是要问“我们应该避免......”。如果这是问题,那么,请记住,main
方法没有特殊规则,如果有理由禁止使用Stream API,那么这个原因也适用于所有其他方法,使得流API是一个无法使用的API。当然,答案是没有理由在main
方法中禁止Stream API。
关于内存消耗,当使用Collection.forEach
方法调用替换for-each循环时,您正在为lambda实例交换Iterator
实例,因此在数量和大小上没有显着差异创建的对象实例。如果您使用Stream的forEach
方法,则添加Spliterator
和Stream
实例,即使您的应用仅包含main
方法,这仍然可以被视为无关紧要。由JVM预先分配的内存远远大于这些少数对象所消耗的内存,并且您的对象很可能适合线程的本地分配存储。换句话说,从JVM的外部,进程使用的内存没有区别。
正如您提到的术语“缓冲区”,您应该知道的概念性事物是,对于大多数操作,Stream都会不缓冲区元素(包括forEach
),所以,无论你是通过循环还是Stream遍历Collection,在这两种情况下都没有分配具有Collection大小的内存缩放,所以差异(如果有的话)仍然如上所述那么小,无论你是否迭代如你的例子中的三个元素或超过三百万个元素。
在可能产生混淆的问题上,您不应在类初始值设定项中使用多线程操作,这意味着您不应在类初始值设定项中使用 parallel 流。但是,这并不是禁止Stream操作本身,main
方法不是类初始化器;当调用main
方法时,该类已经初始化。
答案 1 :(得分:2)
在面试问题中,不要假设每个是/否问题仅限于这两个选择。一个好的答案可能是“无论如何都没有区别”。
在这种情况下,他们可能一直在寻找您认识到list.foreach()
比list.stream().foreach()
更有效。