Stream 主方法中的Java8流

Stream 主方法中的Java8流,stream,java-8,Stream,Java 8,有人在采访中问我,我们是否应该在主方法中编写流式操作 这有什么区别吗 例如: 职业运动员{ 私有字符串名称; 私有int-id; 公共运动员(字符串名称,整数id){ this.name=名称; this.id=id; } } 公开庭审{ 公共静态void main(字符串[]args){ 列表=新的ArrayList(); 添加(新运动员(“约翰”,1)); 添加(新运动员(“Jim”,2)); 增加(新运动员(“Jojo”,3)); list.stream().forEach(System

有人在采访中问我,我们是否应该在主方法中编写流式操作

这有什么区别吗

例如:

职业运动员{
私有字符串名称;
私有int-id;
公共运动员(字符串名称,整数id){
this.name=名称;
this.id=id;
}
}
公开庭审{
公共静态void main(字符串[]args){
列表=新的ArrayList();
添加(新运动员(“约翰”,1));
添加(新运动员(“Jim”,2));
增加(新运动员(“Jojo”,3));
list.stream().forEach(System.out::print);//或任何其他流操作
}
}
所以我只是想知道这是否有什么不同。。。现在,我唯一知道的是,一旦流被消耗,它就不能再被消耗

那么,它是否会影响JVM中的内存或为流式处理创建缓冲内存


如果有的话?为什么不在主要方法中使用此选项?

在面试问题中,不要假设每个是/否问题都局限于这两个选项。一个好的答案可能是“两种方式都没有区别”


在这种情况下,他们可能希望您认识到
list.foreach()
list.stream().foreach()更有效。在面试问题中,不要假设每个是/否问题都局限于这两个选项。一个好的答案可能是“两种方式都没有区别”


在这种情况下,他们可能希望您认识到
list.foreach()
list.stream().foreach()
效率更高,“我们是否应该在主方法中编写流操作”是一个复杂的问题。它暗示的第一件事是假设
main
方法有一些特殊之处。无论我们讨论的是哪种操作,如果结论是您可以或不可以在任意方法中使用它们,那么当所讨论的方法是
main
方法时,没有理由得出不同的结论

显然,“我们应该……”的意思是问“我们应该避免……”。如果这是个问题,那么请记住,
main
方法没有特殊规则,如果有理由禁止使用流API,那么这个理由也适用于所有其他方法,使流API成为不可用的API。当然,答案是没有理由禁止
main
方法中的流API


关于内存消耗,当使用
集合.forEach
方法调用替换for each循环时,您正在用一个
迭代器
实例交换一个lambda实例,因此创建的对象实例的数量和大小没有显着差异。如果使用Stream的
forEach
方法,则添加一个
Spliterator
和一个
Stream
实例,即使您的应用程序仅包含
main
方法,这两个实例仍然可以被视为无关紧要。JVM预先分配的内存远远大于这几个对象所消耗的内存,您的对象很可能适合线程的本地分配存储。换句话说,从JVM的外部来看,进程所使用的内存没有差别

正如您提到的术语“缓冲区”,概念上您应该知道的是,流不会为大多数操作(包括
forEach
)缓冲元素,因此,无论您是通过循环还是流遍历集合,在这两种情况下,都不会分配与集合大小相关的内存缩放,因此,如果有,则保持如上所述的小,而不管您是像示例中那样迭代三个元素还是超过三百万个元素



可能引起混淆的一个问题是,不应该在类初始值设定项中使用多线程操作,这意味着不应该在类初始值设定项中使用并行流。但这并不禁止流操作本身,而且,
main
方法不是类初始值设定项;调用
main
方法时,类已经初始化。

是否“应该在main方法中编写流操作”是一个已加载的问题。它暗示的第一件事是假设
main
方法有一些特殊之处。无论我们讨论的是哪种操作,如果结论是您可以或不可以在任意方法中使用它们,那么当所讨论的方法是
main
方法时,没有理由得出不同的结论

显然,“我们应该……”的意思是问“我们应该避免……”。如果这是个问题,那么请记住,
main
方法没有特殊规则,如果有理由禁止使用流API,那么这个理由也适用于所有其他方法,使流API成为不可用的API。当然,答案是没有理由禁止
main
方法中的流API


关于内存消耗,当使用
集合.forEach
方法调用替换for each循环时,您正在用一个
迭代器
实例交换一个lambda实例,因此创建的对象实例的数量和大小没有显着差异。如果使用Stream的
forEach
方法,则添加一个
Spliterator
和一个
Stream
实例,即使您的应用程序仅包含
main
方法,这两个实例仍然可以被视为无关紧要。JVM预先分配的内存远远大于这几个对象所消耗的内存,您的对象很可能适合线程的本地分配存储。换句话说,从JVM的外部,将有n个
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
  }
}