Java 流方法如何操作?

How do Java stream methods operate?

我刚刚了解 Java 流。可以通过在集合上调用 .stream() 来创建流,然后您可以使用 docs.

中描述的方法对该流进行操作

我不明白的是这个过程实际发生的地方。我的意思是确定我可以创建一个具有年龄属性的 Person 对象流并像这样对其进行排序:

Person john = new Person(30);
Person anne = new Person(25);
Person bill = new Person(52);

ArrayList<Person> people = new ArrayList<Person>();
people.add(john);
people.add(anne);
people.add(bill);

ArrayList<Person> sortedPeople = people
.stream()
.sorted(Comparators.comparing(person -> person.getAge()))
.collect(ArrayList::new, ArrayList::add, ArrayList::addAll);

但是在我发现的文档和源代码中,像包含排序方法的函数接口没有排序代码,只是描述传递给它的 lambda 函数。 我在这里是不是误解了什么?

当你调用 ArrayList#stream() 时,你得到了一个看起来像 Stream 但实际上是一些 未指定具体 class 的对象实现了 Stream 接口。

这是 OOP 的一部分优点:我们不知道幕后实际使用了哪些未指定的具体 class,我们也不关心。我们只关心神秘的具体 class(或超级class)履行接口承诺的合同,在本例中为 Stream 接口。

functional interfaces like the one containing the sorted method has no sorting code

未指定的具体 class 实现了排序机制,实现了 Stream 接口要求的 sorted 方法。

just describes the lambda function passed

您传递的 lambda 是将作为排序机制的一部分执行的实际代码。


如果您仍然对那个神秘的混凝土 class 感到好奇,您可以浏览 OpenJDK project. Start here 上找到的 ArrayList#stream 的开源代码。您可能还需要梳理 super-classes 的源代码。

而且,您可以查询 Stream 对象的具体 class。 Java 中的每个对象都是 Object class, so all have a method getClass. Using the Class class 的子 class,你可以为 class.

取一个名字
persons.stream().getClass().getCanonicalName()

当我 运行 使用 Java 17.0.2 实现的副本 Azul Systems 命名为 Zulu 时,我得到:

java.util.stream.ReferencePipeline.Head

我在 the Java 17 API 中没有找到任何这样的 class。因此 class 必须在我当前使用的 Java 的任何实现中进行内部定义。其他实现可能不同,过去和未来的版本也可能不同。

如今,Java 的大多数实现主要基于 OpenJDK 的代码库。这包括 祖鲁语 。所以看看 OpenJDK,我发现 ReferencePipeline.

the source code 中嵌套了 Head class

顺便说一句,你的代码可以简化成这样。

record Person( String name , int age ) { }

List < Person > persons =
        new ArrayList <>(
                List.of(
                        new Person( "Alice" , 52 ) ,
                        new Person( "Bob" , 23 ) ,
                        new Person( "Carol" , 39 )
                )
        );

List < Person > sorted =
        persons
                .stream()
                .sorted( Comparator.comparing( Person :: age ) )
                .toList();

persons.toString() = [Person[name=Alice, age=52], Person[name=Bob, age=23], Person[name=Carol, age=39]]

sorted.toString() = [Person[name=Bob, age=23], Person[name=Carol, age=39], Person[name=Alice, age=52]]