当前位置: 首页 > 知识库问答 >
问题:

Java8可选vs流中的嵌套空检查

古畅
2023-03-14
import lombok.AllArgsConstructor;
import lombok.Getter;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

public class NestedObjectsStreamTest {
    @Getter @AllArgsConstructor
    private static class A {
        private B b;
    }
    @Getter @AllArgsConstructor
    private static class B {
        private C c;
    }
    @Getter @AllArgsConstructor
    private static class C {
        private D d;
    }
    @Getter @AllArgsConstructor
    private static class D {
        private String value;
    }

    public static void main(String[] args) {
        A a0 = new A(new B(new C(new D("a0"))));
        A a1 = new A(new B(new C(new D("a1"))));
        A a2 = new A(new B(new C(new D(null))));
        A a3 = new A(new B(new C(null)));
        A a5 = new A(new B(null));
        A a6 = new A(null);
        A a7 = null;

        System.out.println("getValue(a0) = " + getValue(a0));
        System.out.println("getValue(a1) = " + getValue(a1));
        System.out.println("getValue(a2) = " + getValue(a2));
        System.out.println("getValue(a3) = " + getValue(a3));
        System.out.println("getValue(a5) = " + getValue(a5));
        System.out.println("getValue(a6) = " + getValue(a6));
        System.out.println("getValue(a7) = " + getValue(a7));

        List<A> aList = Arrays.asList(a0, a1, a2, a3, a5, a6, a7);

        System.out.println("getValues(aList) " + getValues(aList));
    }

    private static String getValue(final A a) {
        return Optional.ofNullable(a)
            .map(A::getB)
            .map(B::getC)
            .map(C::getD)
            .map(D::getValue)
            .orElse("default");
    }

    private static List<String> getValues(final List<A> aList) {
        return aList.stream()
            .filter(Objects::nonNull)
            .map(A::getB)
            .filter(Objects::nonNull)
            .map(B::getC)
            .filter(Objects::nonNull)
            .map(C::getD)
            .filter(Objects::nonNull)
            .map(D::getValue)
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
    }
}

输出

getValue(a0) = a0
getValue(a1) = a1
getValue(a2) = default
getValue(a3) = default
getValue(a5) = default
getValue(a6) = default
getValue(a7) = default

getValues(aList) [a0, a1]

共有1个答案

孟胤
2023-03-14

下面是您可以尝试的代码:

aList.stream()
    .map(applyIfNotNull(A::getB))
    .map(applyIfNotNull(B::getC))
    .map(applyIfNotNull(C::getD))
    .map(applyIfNotNullOrDefault(D::getValue, "default"))
    .filter(Objects::nonNull)
    .forEach(System.out::println);

使用以下实用方法:

public static <T, U> Function<T, U> applyIfNotNull(Function<T, U> mapper) {
  return t -> t != null ? mapper.apply(t) : null;
}

public static <T, U> Function<T, U> applyIfNotNullOrDefault(Function<T, U> mapper, U defaultValue) {
  return t -> t != null ? mapper.apply(t) : defaultValue;
}

public static <T, U> Function<T, U> applyIfNotNullOrElseGet(Function<T, U> mapper, Supplier<U> supplier) {
  return t -> t != null ? mapper.apply(t) : supplier.get();
}

不知道你觉得怎么样。但我个人不喜欢map(...).map(...)...。这里我更喜欢的是:

aList.stream()
    .map(applyIfNotNull(A::getB, B::getC, C::getD))
    .map(applyIfNotNullOrDefault(D::getValue, "default"))
    .filter(Objects::nonNull)
    .forEach(System.out::println);
public static <T1, T2, T3, R> Function<T1, R> applyIfNotNull(Function<T1, T2> mapper1, Function<T2, T3> mapper2,
    Function<T3, R> mapper3) {
  return t -> {
    if (t == null) {
      return null;
    } else {
      T2 t2 = mapper1.apply(t);
      if (t2 == null) {
        return null;
      } else {
        T3 t3 = mapper2.apply(t2);
        return t3 == null ? null : mapper3.apply(t3);
      }
    }
  };
}
 类似资料:
  • 有人能解释一下如何帮助我们避免? 这段代码不是也容易出现吗?如果是这样的话,那么为什么这个代码比 除了帮助我们了解函数是否实际具有返回值之外,还有什么可能的好处

  • 问题内容: 我有一个对象A的列表。此列表中的每个对象A都包含对象B的列表,而对象B包含对象C的列表。对象C包含一个属性名称,我想使用它使用Java 8进行过滤。 如何使用流在Java 8中编写以下代码以避免嵌套循环: 问题答案: 您可以使用两个,然后使用a,然后可以选择第一个,或者如果没有结果返回:

  • 我有一个对象列表A。此列表中的每个对象A都包含对象B的列表,对象B包含对象C的列表。对象C包含一个属性名称,我想使用java 8进行过滤。 如何使用流在java8中编写下面的代码以避免嵌套循环:

  • 我知道Optionals ifPresent()调用的目的是替换空检查。从Oracle文档中提取代码示例,它在简单情况下似乎非常有用。例如: 我只是想了解为什么这被认为比空检查更好。可读性?表演在我看来,这会对项目性能造成影响,因为必须引入一个新的对象才能容纳我们最终希望获得的对象?总之,为什么这是 如果(声卡!=null),则认为比这更好。

  • 下面是我的代码,按预期工作。但我需要用Optional.ofNullable替换它 如何使用

  • 我尝试在两个列表上循环,过滤嵌套列表,并使用java8特性将结果写回主对象。 因此,到目前为止,位置内部的子列表不会更改,这是显而易见的,因为流和收集确实会创建一个新列表,该列表不会写回位置对象中。所以我的问题是,如果有一种方法可以调用位置对象的setSubList(...)方法并将新列表写入其中。 感谢