Java 流操作

这是《Java日历 | 2021年圣诞降临时序文的第15天的文章》。

※ 我喝了一点点。

简介

我已经确认了在Java的Stream和List(等)中处理约1000个对象时,堆(内存)的使用量会如何变化。

结果看起来使用Stream比List要快四分之一。仅仅这一点就能感受到使用Stream的好处,不是吗?

在处理大量数据的场景中,建议使用专用框架,例如Spring Batch,而不是使用Stream API。所以,它似乎更适用于相对数量有限的用途。

一组被比较的程式码

下面是一个将代码生成1000个对象并将它们放入列表中(从Stream转换为List)的示例。

如果你使用 Stream

    void useStream() {
        IntStream.range(0, 1000).parallel().mapToObj(i -> create()).collect(Collectors.toList());
    }
只有通过使用parallel(),才能得到这样的结果。如果不使用parallel(),结果几乎与使用List相同,或者稍微大一点。非常抱歉的结果。

如果要使用List

    void useList() {
        List<Parson> l = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            l.add(create());
        }
    }

測量結果

在测量中,我们使用了之前的文章《使用Java进行堆大小测量 JUnit5教程》中使用的quickperf。

如果使用Stream。

[QUICK PERF] Measured heap allocation (test method thread): 137.34 Kilo bytes (140 640 bytes)

使用列表的情况下

[QUICK PERF] Measured heap allocation (test method thread): 510.02 Kilo bytes (522 264 bytes)

付録 – 附录

整个测试代码

@QuickPerfTest
public class StreamVsListTest {

    @MeasureHeapAllocation
    @Test
    void useStream() {
        IntStream.range(0, 1000).parallel().mapToObj(i -> create()).collect(Collectors.toList());
    }

    @MeasureHeapAllocation
    @Test
    void useList() {
        List<Parson> l = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            l.add(create());
        }
    }

    @AllArgsConstructor
    @Data
    class Parson {
        private String name;
        private int age;
        private String addr;
        private String addr2;
    }

    Parson create() {
        return new Parson(RandomStringUtils.randomAlphabetic(10), new Random().nextInt(), RandomStringUtils.randomAlphabetic(20), RandomStringUtils.randomAlphabetic(20));
    }

}