【问题标题】:Java 8 streams nonNull on properties of objectsJava 8 在对象的属性上流式传输 nonNull
【发布时间】:2023-03-04 03:26:01
【问题描述】:

我有以下 sn-p 收集具有 name 字符串属性的特定对象,该字符串属性包含特定过滤器 filterName

List<Foo> filteredFoo= fooList.stream()
                .filter(Objects::nonNull)
                .filter(myFoo -> {
                            if (Strings.isNullOrEmpty(myFoo.getName()))
                                return false;
                            return myFoo.getName().contains(filterName);
                        }
                ).collect(Collectors.toList());

它按预期工作,但我想知道是否有一种更优雅的方式来以函数方式编写 if-statement,并以比在过滤器中使用条件块更好的方式检查空属性或空属性。

【问题讨论】:

  • 我很困惑。您已决定 Objects::nonNull 需要是一个单独的过滤器,但其他所有内容都需要放在一个单独的过滤器中。为什么会这样?
  • @zeroflagL 这样做是为了便于阅读, Objects:nonNull 在对象级别工作,其中第二个过滤器作用于对象本身的属性。我不知道从性能的角度来看这是否有任何影响,但为了便于阅读,我认为它很有用。
  • 这就是我的观点:如果您力求可读性,那么为什么要使用复杂的第二个过滤器,而不是像Foo::hasName 这样的单独且可能可重复使用的过滤器?
  • 我对 java8 很陌生,我的直觉是自定义过滤器需要在我的模型中进行一些实现,对吧?在这种情况下,这是唯一使用过滤的地方,因此我的问题是:如果只使用一次自定义过滤器是否有意义?如果是的话,我想举一个例子来说明它是如何实现的。有人可能会觉得它很有用。

标签: java filter java-8 java-stream


【解决方案1】:

将第二个filter 替换为以下内容:

.filter(myFoo -> Optional.ofNullable(myFoo.getName())
                         .filter(n -> n.contains(filterName))
                         .isPresent())

甚至:

.filter(myFoo -> {
    String name = myFoo.getName();
    return name != null && name.contains(filterName)
 })

【讨论】:

  • 在您的第一个示例中,!Strings.isNullOrEmpty(n) 毫无意义。
  • @zero 你能解释一下吗? name 可能是 null 或为空。可选仅解决第一种情况 imo。
  • 是否为空无所谓。一个空字符串不包含filterName,无论如何你都要检查一下。另外!n.isEmpty() 会更简洁。
  • 不过,!Strings.isNullOrEmpty(name) &amp;&amp; name.contains(filterName) 是不必要的冗长。除非您想不惜一切代价向您的项目添加第 3 方库要求,否则您可以简单地说 name!=null &amp;&amp; name.contains(filterName)。正如@zeroflagL 已经指出的那样,隐含的isEmpty() 检查已过时,您不需要用于普通…!=null 检查的实用方法。
【解决方案2】:

选择函数式风格,结果表达式:

.filter(foo -> foo.getName() != null && foo.getName().contains(filterName))

拆分不会带来更多的简单性:

.filter(foo -> foo.getName() != null)
.filter(foo -> foo.getName().contains(filterName))

在 Foo::getName (Objects::isNull) 上使用谓词也太复杂了,只是为了节省变量。

如果 filterName 本身不为空,则不需要 Strings.isEmptyOrNull。

【讨论】:

    【解决方案3】:

    如果您有权访问 Foo 类,则将 if 条件移至方法 isSameName 并使用如下过滤器

    filter(myFoo -> {return myFoo.isSameName(filterName);})
    

    【讨论】:

      猜你喜欢
      • 2014-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-10
      • 1970-01-01
      • 2022-12-23
      • 1970-01-01
      • 2016-11-24
      相关资源
      最近更新 更多