You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用相同Comparator时Stream.sorted遇null不抛NPE而List.sort会?

为何list.stream().sorted(comp)与list.sort(comp)处理含null属性对象时表现不同?

代码示例

public class ToSort {
    private String sortBy;

    public ToSort(String sortBy) {
        this.sortBy = sortBy;
    }
    public String getSortBy() {
        return sortBy;
    }

    public static void main(String[] args) {
        Comparator<ToSort> comp = Comparator.comparing(ToSort::getSortBy);

        ToSort o1 = new ToSort("TEST");
        ToSort o2 = new ToSort(null);

        List list = new ArrayList<>();
        list.add(o1);
        list.add(o2);

        list.stream().sorted(comp); // ok
        list.sort(comp); // NullPointerException
    }
}

运行输出

Exception in thread "main" java.lang.NullPointerException
    at java.base/java.util.Comparator.lambda$comparing$77a9974f$1(Comparator.java:469)
    at java.base/java.util.TimSort.countRunAndMakeAscending(TimSort.java:355)
    at java.base/java.util.TimSort.sort(TimSort.java:220)
    at java.base/java.util.Arrays.sort(Arrays.java:1515)
    at java.base/java.util.ArrayList.sort(ArrayList.java:1750)
    at com.oxand.simeox.model.pojo.ToSort.main(ToSort.java:28)

差异原因分析

核心差异来自两个方法的执行时机和底层实现逻辑:

  • list.stream().sorted(comp)未触发实际排序:
    Stream是惰性求值的,sorted()方法仅创建一个标记了“待排序”状态的Stream对象,不会立即执行排序操作。只有当调用终止操作(比如collect()、forEach()、toArray()等)时,才会真正执行排序逻辑。你代码里仅调用了sorted(),没有后续终止操作,排序根本没执行,自然不会触发空指针异常。
    补充:如果给Stream加上终止操作,比如list.stream().sorted(comp).collect(Collectors.toList()),同样会抛出NPE,此时会执行实际排序,比较逻辑和list.sort()完全一致。

  • list.sort(comp)立即执行排序并触发NPE:
    ArrayList的sort()方法底层依赖Arrays.sort,而Arrays.sort使用TimSort算法。TimSort在排序前会先执行countRunAndMakeAscending方法,该方法会遍历元素、尝试构建连续有序的序列,过程中会调用Comparator比较相邻元素。Comparator.comparing(ToSort::getSortBy)生成的比较器,会尝试让null属性与非null属性调用compareTo方法,而null无法调用方法,必然抛出NullPointerException。

内容的提问来源于stack exchange,提问作者Jesus Zavarce

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 10:15:27