案例

  1. List<User> children = Lists.newArrayList(new User("bcd", 1, null));
  2. children.add(new User("a", 1, null));
  3. children.add(new User("d", 1, null));
  4. children.add(new User(null, 1, null));
  5. children.sort(Comparator.nullsLast(Comparator.comparing(User::getName)));

image.png

定位原因

image.png
此处看到这个是否是null是针对的集合本身元素,而并不是mapping之后的值!!!
当元素本身不是null的时候, 也就是else里面,还是会去走mapping之后的compare,见下。
image.png
image.png
可以看到String的CompareTo方法入参是@NotNull的,所以报错了。

结论

nullFirstnullLast 和我正常理解的null的值会放在最前面和最后面不一样,根据源码可以看出,针对是还是元素本身。当元素不是null的时候,最终会对keyExtractor.apply得到的值的比较,此时如果存在null,就会报NPE。

解决

重写Comparator

  1. children.sort((u1,u2) -> {
  2. if (StringUtils.isEmpty(u1.getName())) {
  3. return 1;
  4. }
  5. if (StringUtils.isEmpty(u2.getName())) {
  6. return -1;
  7. }
  8. return u1.getName().compareTo(u2.getName());
  9. });