Как избежать NullPointerExceptions в лямбда-компараторах?

Я хочу сравнить два заданных объекта, которые могут быть пустыми во время выполнения. В моем примере:

@Test
public void shouldCompareAgents() {

    Agent a1 = new Agent();
    a1.setId("4711");
    a1.setType(null);

    Agent a2 = new Agent();
    a2.setId(a1.getId());
    a2.setType(a1.getType());

    assertEquals("Agent.getId", 0,
            Comparator.comparing(Agent::getId).compare(a1, a2));

    assertEquals("Agent.getType", 0,
            Comparator.comparing(Agent::getType).compare(a1, a2));
}

Утверждение id работает нормально, по типу не как a1.getType() равно null. Есть ли способ избежать этого? Я пробовал Comparator.nullsLast(...), но это не имеет смысла, поскольку я не сортирую элементы здесь.

У меня есть много утверждений, поэтому я бы предпочел "однострочный" . Я новичок в лямбда-выражениях.

Ответ 1

Если вы просто хотите использовать это в тесте JUnit, почему бы вам просто не передать объекты, которые хотите сравнить непосредственно с методом assertEquals?

assertEquals("Agent.getId", a1.getId(), a2.getId());

Это также помогает JUnit генерировать полезное сообщение об ошибке при неудаче теста.

Если вы хотите сделать это в производственном коде, вы можете использовать Objects.equals:

if (Objects.equals(a1.getId(), a2.getId())) { ... }

который присутствует с Java 7.

Ответ 2

Что-то вроде этого:

Comparator.comparing(Agent::getType, 
    Comparator.nullsLast(Comparator.naturalOrder()))

Поскольку вам нужно, чтобы это использовалось в других местах, вы можете извлечь его как:

    private static <R, T extends Comparable<T>> boolean areEqual(R left, R right, Function<R, T> function) {
         return Comparator.comparing(
                 function, 
                 Comparator.nullsLast(Comparator.naturalOrder())) 
                           .compare(left, right) == 0;
}

Ответ 3

Вы можете использовать Objects.equals:

assertEquals("Agent.getId", true,
    Objects.equals(a1.getID(),a2.getID());

assertEquals("Agent.getType", true,
    Objects.equals(a1.getType(),a2.getType());

Objects.equals обрабатывает null для вас.