有人在一次采访中问我,我们是否应该以主要的方式编写流媒体操作。
有什么区别吗?
例如:
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中为流创建缓冲区内存?
如果是?为什么在主要方法中不使用这一方法呢?
发布于 2016-05-17 11:34:47
“我们应该在主方法中编写流操作”的问题是一个加载的问题。它所暗示的第一件事是假设main方法有一些特殊之处。不管我们讨论的是哪些操作,如果结论是您可以或不可能在任意的方法中使用它们,那么当所讨论的方法是main方法时,您没有理由得出不同的结论。
显然,“我们应该…”实际上是要问“我们是否应该避免…”。如果这就是问题所在,那么请记住,main方法没有特殊的规则,如果有理由禁止使用Stream,那么这个原因也适用于所有其他方法,从而使Stream成为不可用的API。当然,答案是没有理由禁止在main方法中使用Stream。
关于内存消耗,当用Collection.forEach方法调用替换for -每个循环时,您将一个Iterator实例交换为一个lambda实例,因此在创建的对象实例的数量和大小上没有明显的差别。如果使用Stream的forEach方法,则添加一个Spliterator和一个Stream实例,即使应用程序仅由main方法组成,这些实例仍然可以被认为是无关紧要的。JVM预先分配的内存比这几个对象占用的内存要大得多,而且您的对象很可能适合线程的本地分配存储。换句话说,从JVM外部看,进程使用的内存没有什么不同。
正如您提到的“缓冲区”一词,您应该知道的概念是,对于大多数操作(包括forEach),流不需要缓冲元素,因此,无论您是通过循环还是通过流遍历集合,在这两种情况下,都没有分配到与集合大小相同的内存,因此,如果有的话,两者之间的差异仍然和上面描述的一样小,无论您是像在示例中那样迭代三个元素,还是超过300万个元素。
对于可能造成混淆的问题,您不应该在类初始化器中使用多线程操作,这意味着您不应该在类初始化器中使用并行流。但是这本身并不禁止流操作,而且,main方法不是类初始化器;当调用main方法时,类已经初始化了。
发布于 2016-05-16 13:07:05
在面试问题中,不要认为每一个是/否问题都局限于这两种选择。一个好的答案可能是“任何一种方式都没有区别”。
在这种情况下,他们可能一直在寻找您认识到list.foreach()比list.stream().foreach()更有效。
https://stackoverflow.com/questions/37249051
复制相似问题