当前位置:首页 > 科技  > 软件

为什么list.sort()比Stream().sorted()更快?

来源: 责编: 时间:2023-09-18 21:41:46 477观看
导读看到一个评论,里面提到了list.sort()和list.strem().sorted()排序的差异。说到list.sort()排序比stream().sorted()排序性能更好。但没说到为什么。有朋友也提到了这一点。本文重新开始,先问是不是,再问为什么。真的更好

看到一个评论,里面提到了list.sort()和list.strem().sorted()排序的差异。YWA28资讯网——每日最新资讯28at.com

说到list.sort()排序比stream().sorted()排序性能更好。YWA28资讯网——每日最新资讯28at.com

但没说到为什么。YWA28资讯网——每日最新资讯28at.com

YWA28资讯网——每日最新资讯28at.com

有朋友也提到了这一点。YWA28资讯网——每日最新资讯28at.com

本文重新开始,先问是不是,再问为什么。YWA28资讯网——每日最新资讯28at.com

真的更好吗?

先简单写个 demo。YWA28资讯网——每日最新资讯28at.com

List<Integer> userList = new ArrayList<>();    Random rand = new Random();    for (int i = 0; i < 10000 ; i++) {        userList.add(rand.nextInt(1000));    }    List<Integer> userList2 = new ArrayList<>();    userList2.addAll(userList);    Long startTime1 = System.currentTimeMillis();    userList2.stream().sorted(Comparator.comparing(Integer::intValue)).collect(Collectors.toList());    System.out.println("stream.sort耗时:"+(System.currentTimeMillis() - startTime1)+"ms");    Long startTime = System.currentTimeMillis();    userList.sort(Comparator.comparing(Integer::intValue));    System.out.println("List.sort()耗时:"+(System.currentTimeMillis()-startTime)+"ms");

输出:YWA28资讯网——每日最新资讯28at.com

stream.sort耗时:62msList.sort()耗时:7ms

由此可见 list 原生排序性能更好。YWA28资讯网——每日最新资讯28at.com

能证明吗?YWA28资讯网——每日最新资讯28at.com

不一定吧。YWA28资讯网——每日最新资讯28at.com

再把 demo 变换一下,先输出stream.sort。YWA28资讯网——每日最新资讯28at.com

List<Integer> userList = new ArrayList<>();Random rand = new Random();for (int i = 0; i < 10000 ; i++) {    userList.add(rand.nextInt(1000));}List<Integer> userList2 = new ArrayList<>();userList2.addAll(userList);Long startTime = System.currentTimeMillis();userList.sort(Comparator.comparing(Integer::intValue));System.out.println("List.sort()耗时:"+(System.currentTimeMillis()-startTime)+"ms");Long startTime1 = System.currentTimeMillis();userList2.stream().sorted(Comparator.comparing(Integer::intValue)).collect(Collectors.toList());System.out.println("stream.sort耗时:"+(System.currentTimeMillis() - startTime1)+"ms");

此时输出变成了:YWA28资讯网——每日最新资讯28at.com

List.sort()耗时:68msstream.sort耗时:13ms

这能证明上面的结论错误了吗?YWA28资讯网——每日最新资讯28at.com

都不能。YWA28资讯网——每日最新资讯28at.com

两种方式都不能证明到底谁更快。YWA28资讯网——每日最新资讯28at.com

使用这种方式在很多场景下是不够的,某些场景下,JVM 会对代码进行 JIT 编译和内联优化。YWA28资讯网——每日最新资讯28at.com

Long startTime = System.currentTimeMillis();...System.currentTimeMillis() - startTime

此时,代码优化前后执行的结果就会非常大。YWA28资讯网——每日最新资讯28at.com

基准测试是指通过设计科学的测试方法、测试工具和测试系统,实现对一类测试对象的某项性能指标进行定量的和可对比的测试。YWA28资讯网——每日最新资讯28at.com

基准测试使得被测试代码获得足够预热,让被测试代码得到充分的 JIT 编译和优化。YWA28资讯网——每日最新资讯28at.com

下面是通过 JMH 做一下基准测试,分别测试集合大小在 100,10000,100000 时两种排序方式的性能差异。YWA28资讯网——每日最新资讯28at.com

import org.openjdk.jmh.annotations.*;import org.openjdk.jmh.infra.Blackhole;import org.openjdk.jmh.results.format.ResultFormatType;import org.openjdk.jmh.runner.Runner;import org.openjdk.jmh.runner.RunnerException;import org.openjdk.jmh.runner.options.Options;import org.openjdk.jmh.runner.options.OptionsBuilder;import java.util.*;import java.util.concurrent.ThreadLocalRandom;import java.util.concurrent.TimeUnit;import java.util.stream.Collectors;@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.MICROSECONDS)@Warmup(iterations = 2, time = 1)@Measurement(iterations = 5, time = 5)@Fork(1)@State(Scope.Thread)public class SortBenchmark {    @Param(value = {"100", "10000", "100000"})    private int operationSize;     private static List<Integer> arrayList;    public static void main(String[] args) throws RunnerException {        // 启动基准测试        Options opt = new OptionsBuilder()            .include(SortBenchmark.class.getSimpleName())             .result("SortBenchmark.json")            .mode(Mode.All)            .resultFormat(ResultFormatType.JSON)            .build();        new Runner(opt).run();     }    @Setup    public void init() {        arrayList = new ArrayList<>();        Random random = new Random();        for (int i = 0; i < operationSize; i++) {            arrayList.add(random.nextInt(10000));        }    }    @Benchmark    public void sort(Blackhole blackhole) {        arrayList.sort(Comparator.comparing(e -> e));        blackhole.consume(arrayList);    }    @Benchmark    public void streamSorted(Blackhole blackhole) {        arrayList = arrayList.stream().sorted(Comparator.comparing(e -> e)).collect(Collectors.toList());        blackhole.consume(arrayList);    }}

性能测试结果:YWA28资讯网——每日最新资讯28at.com

YWA28资讯网——每日最新资讯28at.com

可以看到,list.sort()效率确实比stream().sorted()要好。YWA28资讯网——每日最新资讯28at.com

为什么更好?YWA28资讯网——每日最新资讯28at.com

流本身的损耗

java 的 stream 让我们可以在应用层就可以高效地实现类似数据库 SQL 的聚合操作了,它可以让代码更加简洁优雅。YWA28资讯网——每日最新资讯28at.com

但是,假设我们要对一个 list 排序,得先把 list 转成 stream 流,排序完成后需要将数据收集起来重新形成 list,这部份额外的开销有多大呢?YWA28资讯网——每日最新资讯28at.com

我们可以通过以下代码来进行基准测试:YWA28资讯网——每日最新资讯28at.com

import org.openjdk.jmh.annotations.*;import org.openjdk.jmh.infra.Blackhole;import org.openjdk.jmh.results.format.ResultFormatType;import org.openjdk.jmh.runner.Runner;import org.openjdk.jmh.runner.RunnerException;import org.openjdk.jmh.runner.options.Options;import org.openjdk.jmh.runner.options.OptionsBuilder;import java.util.ArrayList;import java.util.Comparator;import java.util.List;import java.util.Random;import java.util.concurrent.TimeUnit;import java.util.stream.Collectors;@BenchmarkMode(Mode.AverageTime)@OutputTimeUnit(TimeUnit.MICROSECONDS)@Warmup(iterations = 2, time = 1)@Measurement(iterations = 5, time = 5)@Fork(1)@State(Scope.Thread)public class SortBenchmark3 {    @Param(value = {"100", "10000"})    private int operationSize; // 操作次数    private static List<Integer> arrayList;    public static void main(String[] args) throws RunnerException {        // 启动基准测试        Options opt = new OptionsBuilder()            .include(SortBenchmark3.class.getSimpleName()) // 要导入的测试类            .result("SortBenchmark3.json")            .mode(Mode.All)            .resultFormat(ResultFormatType.JSON)            .build();        new Runner(opt).run(); // 执行测试    }    @Setup    public void init() {        // 启动执行事件        arrayList = new ArrayList<>();        Random random = new Random();        for (int i = 0; i < operationSize; i++) {            arrayList.add(random.nextInt(10000));        }    }    @Benchmark    public void stream(Blackhole blackhole) {        arrayList.stream().collect(Collectors.toList());        blackhole.consume(arrayList);    }    @Benchmark    public void sort(Blackhole blackhole) {        arrayList.stream().sorted(Comparator.comparing(Integer::intValue)).collect(Collectors.toList());        blackhole.consume(arrayList);    }}

方法 stream 测试将一个集合转为流再收集回来的耗时。YWA28资讯网——每日最新资讯28at.com

方法 sort 测试将一个集合转为流再排序再收集回来的全过程耗时。YWA28资讯网——每日最新资讯28at.com

测试结果如下:YWA28资讯网——每日最新资讯28at.com

YWA28资讯网——每日最新资讯28at.com

可以发现,集合转为流再收集回来的过程,肯定会耗时,但是它占全过程的比率并不算高。YWA28资讯网——每日最新资讯28at.com

因此,这部只能说是小部份的原因。YWA28资讯网——每日最新资讯28at.com

排序过程

我们可以通过以下源码很直观的看到。YWA28资讯网——每日最新资讯28at.com

YWA28资讯网——每日最新资讯28at.com

  • 1 begin方法初始化一个数组。
  • 2 accept 接收上游数据。
  • 3 end 方法开始进行排序。

这里第 3 步直接调用了原生的排序方法,完成排序后,第 4 步,遍历向下游发送数据。YWA28资讯网——每日最新资讯28at.com

所以通过源码,我们也能很明显地看到,stream()排序所需时间肯定是 > 原生排序时间。YWA28资讯网——每日最新资讯28at.com

只不过,这里要量化地搞明白,到底多出了多少,这里得去编译 jdk 源码,在第 3 步前后将时间打印出来。YWA28资讯网——每日最新资讯28at.com

这一步我就不做了。YWA28资讯网——每日最新资讯28at.com

感兴趣的朋友可以去测一下。YWA28资讯网——每日最新资讯28at.com

不过我觉得这两点也能很好地回答,为什么list.sort()比Stream().sorted()更快。YWA28资讯网——每日最新资讯28at.com

补充说明:YWA28资讯网——每日最新资讯28at.com

  • 本文说的 stream() 流指的是串行流,而不是并行流。
  • 绝大多数场景下,几百几千几万的数据,开心就好,怎么方便怎么用,没有必要去计较这点性能差异。

本文链接:http://www.28at.com/showinfo-26-10468-0.html为什么list.sort()比Stream().sorted()更快?

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: C++中表达式的必要性

下一篇: 分布式事务原理及解决方案

标签:
  • 热门焦点
  • 对标苹果的灵动岛 华为带来实况窗功能

    继苹果的灵动岛之后,华为也在今天正式推出了“实况窗”功能。据今天鸿蒙OS 4.0的现场演示显示,华为的实况窗可以更高效的展现出实时通知,比如锁屏上就能看到外卖、打车、银行
  • 破圈是B站头上的紧箍咒

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之每年的暑期档都少不了瞄准追剧女孩们的古偶剧集,2021年有优酷的《山河令》,2022年有爱奇艺的《苍兰诀》,今年却轮到小破站抓住了追
  • 拼多多APP上线本地生活入口,群雄逐鹿万亿市场

    Tech星球(微信ID:tech618)文 | 陈桥辉 Tech星球独家获悉,拼多多在其APP内上线了&ldquo;本地生活&rdquo;入口,位置较深,位于首页的&ldquo;充值中心&rdquo;内,目前主要售卖美食相关的
  • 自律,给不了Keep自由!

    来源 | 互联网品牌官作者 | 李大为编排 | 又耳 审核 | 谷晓辉自律能不能给用户自由暂时不好说,但大概率不能给Keep自由。近日,全球最大的在线健身平台Keep正式登陆港交所,努力
  • 消费结构调整丨巨头低价博弈,拼多多还卷得动吗?

    来源:征探财经作者:陈香羽随着流量红利的退潮,电商的存量博弈越来越明显。曾经主攻中高端与品质的淘宝天猫、京东重拾&ldquo;低价&rdquo;口号。而过去与他们错位竞争的拼多多,靠
  • 消息称小米汽车开始筛选交付中心:需至少120个车位

    IT之家 7 月 7 日消息,日前,有微博简介为“汽车行业从业者、长三角一体化拥护者”的微博用户 @长三角行健者 发文表示,据经销商集团反馈,小米汽车目前
  • 华为和江淮汽车合作开发百万元问界MPV?双方回应来了

    8月1日消息,郭明錤今天在社交平台发文称,华为正在和江淮汽车合作,开发售价在100万元的问界MPV,预计在2024年第2季度量产,销量目标为上市首年交付5万辆。
  • 7月4日见!iQOO 11S官宣:“鸡血版”骁龙8 Gen2+200W快充加持

    上半年已接近尾声,截至目前各大品牌旗下的顶级旗舰都已悉数亮相,而下半年即将推出的顶级旗舰已经成为了数码圈爆料的主流,其中就包括全新的iQOO 11S系
  • SN570 NVMe SSD固态硬盘 价格与性能兼具

    SN570 NVMe SSD固态硬盘是西部数据发布的最新一代WD Blue系列的固态硬盘,不仅闪存技术更为精进,性能也得到了进一步的跃升。WD Blue SN570 NVMe SSD的包装外
Top