Java 从流转换<@可空T>;流<@非空T>;使用流api

Java 从流转换<@可空T>;流<@非空T>;使用流api,java,checker-framework,Java,Checker Framework,我使用棋盘格框架 如何从流中删除空值并获得@NonNull对象的集合 Stream<@Nullable T> -> (remove nulls) -> Stream<@NonNull T> Stream->(删除空值)->Stream 以下是执行此操作的代码 import java.util.Objects; import java.util.stream.Stream; import org.checkerframework.checker.nullnes

我使用棋盘格框架

如何从流中删除空值并获得@NonNull对象的集合

Stream<@Nullable T> -> (remove nulls) -> Stream<@NonNull T>
Stream->(删除空值)->Stream

以下是执行此操作的代码

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);
  }

}
导入java.util.Objects;
导入java.util.stream.stream;
导入org.checkerframework.checker.nullness.qual.NonNull;
导入org.checkerframework.checker.nullness.qual.Nullable;
类RemoveNullsFromStream{
@SuppressWarnings(“nullness”)//nullness检查器不是硬编码的
//筛选器和对象的实现详细信息::nonNull
流removeNullsFromStream(流参数){
返回参数过滤器(对象::非空);
}
}
请注意使用
@SuppressWarnings
,因为空值检查器是保守的:它会在无法确定代码是否安全时发出警告。一般来说,
过滤器
的输出与其输入相同;当
filter
的参数为
Objects::nonNull
时,这是一种特殊情况


这种特殊情况可以硬编码到空度检查器中,这将使空度检查器更加精确。此行为当前不是特殊情况,因此您可以使用
@SuppressWarnings

以下是执行此操作的代码

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);
  }

}
导入java.util.Objects;
导入java.util.stream.stream;
导入org.checkerframework.checker.nullness.qual.NonNull;
导入org.checkerframework.checker.nullness.qual.Nullable;
类RemoveNullsFromStream{
@SuppressWarnings(“nullness”)//nullness检查器不是硬编码的
//筛选器和对象的实现详细信息::nonNull
流removeNullsFromStream(流参数){
返回参数过滤器(对象::非空);
}
}
请注意使用
@SuppressWarnings
,因为空值检查器是保守的:它会在无法确定代码是否安全时发出警告。一般来说,
过滤器
的输出与其输入相同;当
filter
的参数为
Objects::nonNull
时,这是一种特殊情况


这种特殊情况可以硬编码到空度检查器中,这将使空度检查器更加精确。此行为目前不是特例,因此您可以使用
@SuppressWarnings

谢谢您的回答。但这些警告看起来很丑陋。我尝试了arg.map(可选::of nullable).filter(可选::isPresent).map(可选::get),但它仍然返回列表。这是CF的错误吗?对我来说,这个长表达式看起来比对
removeNullsFromStream
的简单调用更糟糕。该行为合理且保守:通常,
filter
返回与其参数相同的类型。想想你是如何知道结果是
列表的
,然后试着在类型系统中表达你的论点的步骤;如果您不能,那么
@SuppressWarnings
是天生必需的。那么arg.filter(Objects::nonNull).map(t->(@nonNull t)t)为什么不生成流呢?这看起来像一个;对
map
的调用确实会为具体类型(如
String
)生成
Stream
,但对类型参数(如
t
)不起作用。谢谢您的回答。但这些警告看起来很丑陋。我尝试了arg.map(可选::of nullable).filter(可选::isPresent).map(可选::get),但它仍然返回列表。这是CF的错误吗?对我来说,这个长表达式看起来比对
removeNullsFromStream
的简单调用更糟糕。该行为合理且保守:通常,
filter
返回与其参数相同的类型。想想你是如何知道结果是
列表的
,然后试着在类型系统中表达你的论点的步骤;如果您不能,那么
@SuppressWarnings
是天生必需的。那么arg.filter(Objects::nonNull).map(t->(@nonNull t)t)为什么不生成流呢?这看起来像一个;对
map
的调用确实会为具体类型(如
String
)生成
Stream
,但对类型参数(如
t
)不起作用。