线上报了个NPE,定位问题是nullsLast排序时从map里取到的值为null导致,但既然使用了nullsLast说明开发在写代码时对空指针是有防御意识的,虽然实际没有起到预期的效果。
仔细看了下代码发现大家对nullsLast/nullsFirst的理解并不深,有不少代码写法有问题,导致并不能起到想要的效果。
List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5, 6);
Map<Integer, Integer> map = new HashMap<>();
map.put(4, 400);
map.put(5, 500);
map.put(6, 600);
// Q1: 下面这行代码nullsLast报NPE了,nullsLast应该怎么用?
list.sort(Comparator.nullsLast(Comparator.comparing(map::get)));
// Q2: 下面两行代码的执行结果分别是什么?
list.sort(Comparator.comparing(map::get, Comparator.nullsLast(Integer::compareTo).reversed()));
list.sort(Comparator.comparing(map::get, Comparator.nullsLast(Comparator.reverseOrder())));
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNullPointerException;
@Test
void comparatorNullsLastNpeTest() {
List<Integer> list = Lists.newArrayList(1, 2, 3, 4, 5, 6);
Map<Integer, Integer> map = new HashMap<>();
map.put(4, 400);
map.put(5, 500);
map.put(6, 600);
// Case 1: NPE
List<Integer> finalList = list;
assertThatNullPointerException().isThrownBy(() ->
finalList.sort(Comparator.nullsLast(Comparator.comparing(map::get))));
// Case 2: NPE
assertThatNullPointerException().isThrownBy(() ->
finalList.stream()
.sorted(Comparator.nullsLast(Comparator.comparing(map::get)))
.collect(Collectors.toList()));
// Case 3: Correct
list = Lists.newArrayList(1, 2, 3, 4, 5, 6);
list.sort(Comparator.comparing(map::get, Comparator.nullsLast(Integer::compareTo)));
/// 1,2,3 map对应value为null,放到末尾
assertThat(list).isEqualTo(new ArrayList<>(Arrays.asList(4, 5, 6, 1, 2, 3)));
// Case 4: Correct
list = Lists.newArrayList(1, 2, 3, 4, 5, 6);
list.sort(Comparator.comparing(map::get, Comparator.nullsLast(Integer::compareTo).reversed()));
/// 4,5,6倒序变成6,5,4,[1,2,3]都为null看作整体,nullsLast倒序,变成[1,2,3],6,5,4
assertThat(list).isEqualTo(new ArrayList<>(Arrays.asList(1, 2, 3, 6, 5, 4)));
// Case 5: Correct
list = Lists.newArrayList(1, 2, 3, 4, 5, 6);
list.sort(Comparator.comparing(map::get, Comparator.nullsLast(Integer::compareTo)).reversed());
/// 同Case 4
assertThat(list).isEqualTo(new ArrayList<>(Arrays.asList(1, 2, 3, 6, 5, 4)));
// Case 6: Correct
list = Lists.newArrayList(1, 2, 3, 4, 5, 6);
list.sort(Comparator.comparing(map::get, Comparator.nullsLast(Comparator.reverseOrder())));
/// nullsLast 参数中的comparator用于比较非null值,4,5,6逆序得到6,5,4, 然后1,2,3作为null放末尾
assertThat(list).isEqualTo(new ArrayList<>(Arrays.asList(6, 5, 4, 1, 2, 3)));
// Case 7: Correct
List<Integer> sortedList = list.stream()
.sorted(Comparator.comparing(map::get, Comparator.nullsLast(Integer::compareTo)))
.collect(Collectors.toList());
assertThat(sortedList).isEqualTo(new ArrayList<>(Arrays.asList(4, 5, 6, 1, 2, 3)));
// Case 8: Correct
List<Integer> sortedListReversed = list.stream()
.sorted(Comparator.comparing(map::get, Comparator.nullsLast(Integer::compareTo).reversed()))
.collect(Collectors.toList());
/// 同Case 4
assertThat(sortedListReversed).isEqualTo(new ArrayList<>(Arrays.asList(1, 2, 3, 6, 5, 4)));
// Case 9: Correct
List<Integer> sortedListReversed1 = list.stream()
.sorted(Comparator.comparing(map::get, Comparator.nullsLast(Comparator.reverseOrder())))
.collect(Collectors.toList());
/// 同Case 6
assertThat(sortedListReversed1).isEqualTo(new ArrayList<>(Arrays.asList(6, 5, 4, 1, 2, 3)));
}