主要方法中的Java 8 Stream

时间:2016-05-16 07:48:07

标签: stream java-8

有人在接受采访时问我是否应该用主要方法编写流媒体操作。

这有什么不同吗?

例如:

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中创建用于流式传输的缓冲区内存?

如果是的话?为什么不在主方法中使用它?

2 个答案:

答案 0 :(得分:4)

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

显然,“我们应该......”实际上是要问“我们应该避免......”。如果这是问题,那么,请记住,main方法没有特殊规则,如果有理由禁止使用Stream API,那么这个原因也适用于所有其他方法,使得流API是一个无法使用的API。当然,答案是没有理由在main方法中禁止Stream API。

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

正如您提到的术语“缓冲区”,您应该知道的概念性事物是,对于大多数操作,Stream都会缓冲区元素(包括forEach ),所以,无论你是通过循环还是Stream遍历Collection,在这两种情况下都没有分配具有Collection大小的内存缩放,所以差异(如果有的话)仍然如上所述那么小,无论你是否迭代如你的例子中的三个元素或超过三百万个元素。

在可能产生混淆的问题上,您不应在类初始值设定项中使用多线程操作,这意味着您不应在类初始值设定项中使用 parallel 流。但是,这并不是禁止Stream操作本身,main方法不是类初始化器;当调用main方法时,该类已经初始化。

答案 1 :(得分:2)

在面试问题中,不要假设每个是/否问题仅限于这两个选择。一个好的答案可能是“无论如何都没有区别”。

在这种情况下,他们可能一直在寻找您认识到list.foreach()list.stream().foreach()更有效。