Java Comparator.comparing比较导致空指针异常的解决

Java Comparator.comparing比较导致空指针异常

Comparator.comparing(Department::getOrder)

原因:

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
        Function<? super T, ? extends U> keyExtractor)
{
    Objects.requireNonNull(keyExtractor);
    return (Comparator<T> & Serializable)
        (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
}

如果keyExtractor.apply(c1),那么keyExtractor.apply(c1).compareTo(XX)将报空指针异常

替代方案

Comparator.comparing(Department::getOrder, Comparator.nullsFirst(Comparator.naturalOrder()))

替代方案好处:

public static <T, U> Comparator<T> comparing(
        Function<? super T, ? extends U> keyExtractor,
        Comparator<? super U> keyComparator)
{
    Objects.requireNonNull(keyExtractor);
    Objects.requireNonNull(keyComparator);
    return (Comparator<T> & Serializable)
        (c1, c2) -> keyComparator.compare(keyExtractor.apply(c1),
                                          keyExtractor.apply(c2));
}

会先取出keyExtractor.apply(c1)和keyExtractor.apply(c2),放入比较器进行比较

而Comparator.nullsFirst作为比较器,会创建一个Comparators.NullComparator比较器

public static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
    return new Comparators.NullComparator<>(true, comparator);
}

Comparators.NullComparator比较器的compare接口实现中先进行空值判断处理,不为空的再进行代入比较器比较

/**
 * Null-friendly comparators
 */
final static class NullComparator<T> implements Comparator<T>, Serializable {
    private static final long serialVersionUID = -7569533591570686392L;
    private final boolean nullFirst;
    // if null, non-null Ts are considered equal
    private final Comparator<T> real;
    @SuppressWarnings("unchecked")
    NullComparator(boolean nullFirst, Comparator<? super T> real) {
        this.nullFirst = nullFirst;
        this.real = (Comparator<T>) real;
    }
    @Override
    public int compare(T a, T b) {
        if (a == null) {
            return (b == null) ? 0 : (nullFirst ? -1 : 1);
        } else if (b == null) {
            return nullFirst ? 1: -1;
        } else {
            return (real == null) ? 0 : real.compare(a, b);
        }
    }
    @Override
    public Comparator<T> thenComparing(Comparator<? super T> other) {
        Objects.requireNonNull(other);
        return new NullComparator<>(nullFirst, real == null ? other : real.thenComparing(other));
    }
    @Override
    public Comparator<T> reversed() {
        return new NullComparator<>(!nullFirst, real == null ? null : real.reversed());
    }
}

Comparator中comparing方法的学习

例子:

我们需要根据对象中的name字段进行不规则排序

排序规则为(PPD > 政府 > 合作)

public class Obj {
    private String name;
    private BigDecimal price;
    ......
}
@Test
    public void sort() {
        List<Obj> list =  Arrays.asList(
                new Obj("政府", null),
                new Obj("政府", new BigDecimal("1216.23")),
                new Obj("商业", new BigDecimal("123.23")),
                new Obj("PPD", new BigDecimal("123.23")),
                new Obj("合作", new BigDecimal("127.23")),
                new Obj(null, new BigDecimal("125.23")));
        List<String> sortList =  Arrays.asList("PPD","政府","合作");
        List<Obj> result = list.stream().sorted(
                //先按照name排序(模拟需求的a属性排序)
                Comparator.comparing(Obj::getName,(x,y)-> {
                    if(x == null && y != null){
                        return 1;
                    }else if(x !=null && y == null){
                        return -1;
                    }else if(x == null && y == null){
                        return -1;
                    } else {
                    for(String sort : sortList){
                        if(sort.equals(x) || sort.equals(y)){
                            if(x.equals(y)){
                                return 0;
                            }else if(sort.equals(x)){
                                return -1;
                            }else{
                                return 1;
                            }
                        }
                    }
                    return 0;
                    }
                })).collect(Collectors.toList());
        System.out.println(result);
    }

1.实现

comparing方法有两种实现

方法1:只有一个参数,参数的类型是一个函数式接口

方法2:

问:这个方法中泛型是怎么传递的

1、list.stream()时,获取的stream流已经确定了泛型了,此时返回的对象为Stream<Obj>

2、Stream对象的sorted方法,需要比较器的类型需要是Obj.calss或者是Obj的父类

3、而我们这边调用了静态方法Comparator.comparing,静态方法中的泛型是根据传的参数中的类型来决定的

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java中实现Comparable和Comparator对象比较

    当需要排序的集合或数组不是单纯的数字型时,通常可以使用Comparator或Comparable,以简单的方式实现对象排序或自定义排序. A comparison function, which imposes a total ordering on some collection of objects. Comparators can be passed to a sort method (such as Collections.sort or Arrays.sort) to allow pr

  • Java8 Comparator: 列表排序的深入讲解

    在本文中,我们将看到几个关于如何在Java 8中对List进行排序的示例. 1.按字母顺序排序字符串列表 List<String> cities = Arrays.asList( "Milan", "london", "San Francisco", "Tokyo", "New Delhi" ); System.out.println(cities); //[Milan, london, San

  • Java Comparable和Comparator对比详解

    在实际项目开发过程中,我们经常需要对某个对象或者某个集合中的元素进行排序,常用的两种方式是实现某个接口.常见的可以实现比较功能的接口有Comparable接口和 Comparator接口,那么这两个又有什么区别呢? 关于Comparable接口 关于Comparable接口,其位于 java.lang.Comparable 中,实现这个接口,可以通过重写其 compareTo 方法进行自定义排序,一般用于实体类中,比如针对学生对象,根据其姓名.身高.年龄.地址等进行排序,商品根据名称.库存.价格

  • Java Comparator比较器实例解析

    这篇文章主要介绍了Java Comparator比较器实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 说几点需要注意的,提醒自己即可: 以下是单独定义一个比较器的类,实现了Comparator中的compare方法.(要在Main方法外面定义类噢) 一定是compare而不是Compare哦 package xixixi; import java.util.*; public class Main { public static voi

  • 对比Java中的Comparable排序接口和Comparator比较器接口

    Comparable Comparable 是排序接口. 若一个类实现了Comparable接口,就意味着"该类支持排序". 即然实现Comparable接口的类支持排序,假设现在存在"实现Comparable接口的类的对象的List列表(或数组)",则该List列表(或数组)可以通过 Collections.sort(或 Arrays.sort)进行排序. 此外,"实现Comparable接口的类的对象"可以用作"有序映射(如Tree

  • Java Comparator.comparing比较导致空指针异常的解决

    Java Comparator.comparing比较导致空指针异常 Comparator.comparing(Department::getOrder) 原因: public static <T, U extends Comparable<? super U>> Comparator<T> comparing( Function<? super T, ? extends U> keyExtractor) { Objects.requireNonNull(k

  • java Comparator.comparing排序使用示例

    目录 背景 实体类 示例一 示例二 背景 以前常用的排序方式是通过实现Comparator接口来进行排序,写法相对来说比较复杂,使用Comparator.comparing可以简化代码,看起来逻辑更清晰. 实体类 import lombok.Data; /** * @Author: ck * @Date: 2021/10/12 3:51 下午 */ @Data public class Model { private String name; private int age; } 示例一 通过实

  • Java自动拆箱空指针异常的解决

    公司搬迁,临时充当装修工,提前两个小时到公司忙着拆卸设备.结果接到客户反映,某部分功能偶尔不能用.于是参与救火,与写这段代码的小伙伴一起排查原因. 最终发现导致业务偶尔不能使用是由Long类型自动拆箱导致空指针异常引起的.下面就带大家分析一下Java中基础类型的包装类在拆箱和装箱过程中都做了什么,为什么会出现空指针异常,以及面试过程中会出现的相关面试题. 问题重现 下面通过一个简单的示例才重现一下异常出现的场景. public class BoxTest { public static void

  • Java String转换时为null的解决方法

    开发中经常遇到从集合类List.Map中取出数据转换为String的问题,这里如果处理不好,经常会遇到空指针异常java.lang.NullPointerException,在此总结一下常用转换为String的方法,以及转换后如何对其进行判null使用的问题. Java中对象转换为String的常用方法: 方法一:String  objStr  =  (String) obj: 强制类型转换,对象obj为null,结果也为null,但是obj必须保证其本质是String类型的值,即可转换的值.

  • Java实现ftp文件上传下载解决慢中文乱码多个文件下载等问题

    废话不多说了,直接给大家贴代码了,具体代码如下所示: //文件上传 public static boolean uploadToFTP(String url,int port,String username,String password,String path,String filename,InputStream input) { boolean success=false; FTPClient ftp=new FTPClient();//org.apache.commons.net.ftp

  • 基于java时区转换夏令时的问题及解决方法

    一.准备知识 1.America/New_York的夏令时时间如下: 包左不包右 2016-3-13, 02:00:00到2016-11-6, 02:00:00 2017-3-12, 02:00:00到2017-11-5, 02:00:00 2.三字母时区 ID 为了与 JDK 1.1.x 兼容,一些三字母时区 ID(比如 "PST"."CTT"."AST")也受支持. 但是,它们的使用被废弃,这是因为相同的缩写经常用于多个时区 例如 CST:有

  • JVM---jstack分析Java线程CPU占用,线程死锁的解决

    本文章主要演示在Windows环境,Linux环境也差不多. 一.分析CPU占用飙高 首先写一个Java程序,并模拟一个死循环.让CPU使用率飙高.CPU负载过大的话,新的请求就处理不了了,这就是很多程序变慢了甚至不能访问的原因之一. 下面是我这里的Controller,启动程序之后,开多个请求访问这个方法.死循环代码就不贴了,自己构造.我这里模拟的一个截取字符串的死循环. /** * 演示死循环导致cpu使用率飙高 * */ @RequestMapping("/loop") publ

  • Java使用Arrays.asList报UnsupportedOperationException的解决

    项目场景: 查询多个名销售的销售业绩,上层要求要在查询销售的业绩同事也要查看到每年的年度销售冠军,于是前端传递的是以","分割开的字符串.测试的时候就报错java.lang.UnsupportedOperationException的异常 代码展示: // 这里隐藏了查询条件,所以就写死了 List<String> performId=new ArrayList<>(); performId.add("701728881476112384")

  • idea中使用Inputstream流导致中文乱码解决方法

    1.问题描述 idea中使用Inputstream流导致中文乱码解决方法,当然也不一定就是输入流,可能输出流或者其他用到了流相关的字符的都可能出现乱码,这里有一个可能的解决办法. 2. 解决办法 ① idea中找到下面的路径 File--Settings--Editor--File Encodings ② Transparent native-to-ascii conversion把这个前面勾上,重新创建文件,执行就OK 很多朋友遇到Java FileInputStream读中文乱码问题,下面小

  • java调用process线程阻塞问题的解决

    java调用process线程阻塞问题 项目需求中涉及java调用.bat文件进行图像处理,先直接上简略版程序 public void draw(){ //调用bat脚本进行图像处理 Process process = null; InputStream in = null; try { process = Runtime.getRuntime().exec("startup.bat"); //输出测试 // in = process.getInputStream(); // Stri

随机推荐