2017-02-08 2 views

ответ

2

Вот код, который делает это.

import java.util.Objects; 
import java.util.stream.Stream; 
import org.checkerframework.checker.nullness.qual.NonNull; 
import org.checkerframework.checker.nullness.qual.Nullable; 

class RemoveNullsFromStream { 

    @SuppressWarnings("nullness") // Nullness Checker is not hard-coded with 
        // implementation details of filter and Objects::nonNull 
    <T> 
    Stream<@NonNull T> removeNullsFromStream(Stream<@Nullable T> arg) { 
    return arg.filter(Objects::nonNull); 
    } 

} 

Обратите внимание на использование @SuppressWarnings, потому что Nullness Checker консервативен: он выдает предупреждение, если он не может окончательно доказать, что код безопасности. В общем случае выход filter совпадает с его входом; когда аргументом filter является Objects::nonNull - это особый случай.

Этот специальный корпус может быть жестко закодирован в Nullness Checker, и это сделает точность Nullness Checker более точной. В настоящее время это поведение не является специальным, поэтому вместо этого вы используете @SuppressWarnings.

+0

Благодарим за ответ. Но SuppressWarnings выглядят уродливо. Я попробовал arg.map (Необязательный :: fromNullable) .filter (Необязательный :: isPresent) .map (Необязательный :: get), но он по-прежнему возвращает список <@Nullable T>. Это ошибка CF? –

+1

Для меня это длинное выражение выглядит хуже простого вызова 'removeNullsFromStream'. Поведение звуковое и консервативное: в общем случае 'filter' возвращает тот же тип, что и его аргумент. Подумайте, как вы знаете результат: «List <@Nullable>», а затем попытайтесь выразить шаги вашего аргумента в системе типов; если вы не можете, то '@ SuppressWarnings' по своей сути необходимо. – mernst

+0

Как насчет arg.filter (Объекты :: nonNull) .map (t -> (@NonNull T) t) Почему он не создает поток <@NonNull T>? –