Фильтр ненулевой после mapToLong не работает - PullRequest
0 голосов
/ 12 декабря 2018

мои коды выглядят так

class A {
    private Long b;

    public Long getB() {
        return b;
    }

    public void setB(Long b) {
        this.b = b;
    }

    public static void main(String[] args) {
        A a1 = new A();
        List<A> list = new ArrayList<>();
        list.add(a1);
        list.stream().mapToLong(A::getB).filter(Objects::nonNull).sum();
    }
}

Я хочу отфильтровать ноль, но он не работает, и дает мне исключение NullPointerException.
Если я отфильтрую до mapToLong, например

list.stream().filter(a -> a.getB()!=null).mapToLong(A::getB).sum();

Работает хорошо.Я хочу знать, почему.

Ответы [ 4 ]

0 голосов
/ 12 декабря 2018

Почему этот код не выполняется?

list.stream().mapToLong(A::getB).filter(Objects::nonNull).sum();

Поскольку операции с потоками выполняются последовательно.Поэтому, если для какого-либо элемента потока A::getB не возвращает ненулевое Long, во время сбора будет сгенерировано исключение.

Почему это удается?

list.stream().filter(a -> a.getB()!=null).mapToLong(A::getB).sum();

Поскольку первый выполненный filter() удаляет нулевые элементы, полученные в результате операций a::getB.Таким образом, вы добавляете только ненулевые элементы в поток собиратьТак что не исключение.Но проблема в том, что вы выполняете двойное отображение a::getB.Дублировать и так беспомощно, даже если здесь это не дорого (просто получатель).
То, что вы хотите:

list.stream()       
    .map(A::getB) // return Stream<Long> that may contain null
    .filter(Objects::nonNull) // filter null elements
    .mapToLong(s->s) // map Long to long
    .sum(); // sum
0 голосов
/ 12 декабря 2018

Вы передаете ToLongFunction в mapToLong функцию, и это ее подпись

long applyAsLong(T value);

Вы передаете ссылку на метод A::getB - Здесь она берет ваш b и возвращает его распаковка it (преобразование из Long в примитив long).Так как он равен нулю, это приводит к NPE.

Выполняя фильтрацию ранее, вы избегаете возникновения этой ситуации.

См .: https://docs.oracle.com/javase/tutorial/java/data/autoboxing.html

0 голосов
/ 12 декабря 2018

здесь

list.stream().mapToLong(A::getB).filter(Objects::nonNull).sum();

Вы пытаетесь преобразовать в Long каждый B вашего списка, а затем фильтровать нули.Теперь вы пытаетесь преобразовать нули, потому что вы еще не отфильтровали нули.Это создает исключение NullPointerException.

здесь

list.stream().filter(a -> a.getB()!=null).mapToLong(A::getB).sum();

вы фильтруете нулевые значения, затем сопоставляете и конвертируете их в Long.Здесь нет нулей, когда вы пытаетесь конвертировать, потому что вы уже отфильтровали их, поэтому нет исключения NullPointerException.

0 голосов
/ 12 декабря 2018

mapToLong преобразует Long в long - если это null, вы действительно получите исключение.

Вам необходимо отфильтровать null s перед тем, как конвертация:

list.stream()
    .map(A::getB)
    .filter(Objects::nonNull)   //filter the nulls first
    .mapToLong(Long::longValue) //then convert to primitive
    .sum();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...