如果两个值均为空,则Java Stream返回null

时间:2019-12-02 14:48:54

标签: java java-stream

我有一些字符串,如果任何一个为null,那么我需要返回null。通过Stream实现此目的的方法是什么?还是有更好的方法?

protected String toCombinedString(SomeClass shipment) {
        String prefix1 = ofNullable(shipment)
                .map(SomeClass::getBill)
                .map(Bill::getPrefixString)
                .orElse(null);

       String prefix2 = ofNullable(shipment)
                .map(SomeClass::getBill)
                .map(Bill::getPrefixString)
                .orElse(null);

        String number1 = ofNullable(shipment)
                .map(SomeClass::getBill)
                .map(Bill::getNumberString)
                .orElse(null);

        String number2 = ofNullable(shipment)
                .map(SomeClass::getBill)
                .map(Bill::getNumberString)
                .orElse(null);

              ....

        return Stream.of(prefix1, number1, prefix2, number2...)
                .filter(Objects::nonNull)
                .reduce((a, b) -> a + "-" + b)
                .orElseGet(String::new);
    }

示例输出组合:

唯一可以通过的情况是,每个String都应该为非空或非null,否则返回null

  • 字符串,字符串,字符串,字符串->字符串-字符串-字符串-字符串

6 个答案:

答案 0 :(得分:2)

您似乎执行了三元运算,例如:

return prefix == null || number == null ? null : prefix + "-" + number;

在问题中进行编辑之后,并且条件为仅将String实体中的所有此类Bill类型的属性都考虑在结果中。您可以制定一种从所有属性中提取String的方法,如下所示:

protected String toCombinedString(SomeClass shipment) {
    return Optional.ofNullable(shipment)
            .map(SomeClass::getBill)
            .map(bill -> extractAttributes(bill, Bill::getNumberString, Bill::getPrefixString)) // use this further
            .orElse(null);
}

private String extractAttributes(Bill entity, Function<Bill, String>... mappers) {
    List<String> attributes = Arrays.stream(mappers)
            .map(function -> function.apply(entity))
            .collect(Collectors.toList());
    return attributes.stream().anyMatch(s -> s == null || s.isEmpty()) ?
            null : String.join("-", attributes);
}

答案 1 :(得分:1)

您可以使用

List<String> list = Arrays.asList(prefix1, number1, prefix2, number2...);
return list.contains(null)? null: String.join("-", list);

使用Stream不会有任何改善。临时存储的成本是相同的,因为Stream.of(…)使用临时数组的方式与Arrays.asList(…) varargs 方法通常相同。

但是考虑到每个字符串都是复杂操作的结果,最后一条语句的复杂性或简单性并没有真正的意义。

我宁愿考虑:

String prefix1 = your
                 long
                 complicated
                 operation;
if(prefix1 == null) return null;

String prefix2 = second
                 long
                 complicated
                 operation;
if(prefix2 == null) return null;

String number1 = third
                 long
                 complicated
                 operation;
if(number1 == null) return null;

String number2 = fourth
                 long
                 complicated
                 operation;
if(number2 == null) return null;

…

return String.join("-", prefix1, number1, prefix2, number2 …);

答案 2 :(得分:0)

您可以利用Java 8的Streams的 Count 功能:

Response.render

上面的代码将计算提供的字符串列表中的所有空值。

然后您可以检查计数是否大于0。如果是,则返回null。

long i = list.stream()
             .filter(str -> str == null)
             .count();

答案 3 :(得分:0)

我认为流会使事情复杂化,在处理数据的集合或聚合时应使用流。

这是一个不使用流的示例:

Enumerating objects: 17, done.
Counting objects: 100% (17/17), done.
Delta compression using up to 4 threads
Compressing objects: 100% (16/16), done.
Writing objects: 100% (17/17), 3.01 KiB | 440.00 KiB/s, done.
Total 17 (delta 3), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Python app detected
remote: -----> Installing python-3.6.9
remote: -----> Installing pip
remote: -----> Installing SQLite3
remote:  !     Push rejected, failed to compile Python app.
remote:
remote:  !     Push failed
remote: Verifying deploy...
remote:
remote: !       Push rejected to scumbotfin.
remote:
To https://git.heroku.com/scumbotfin.git
 ! [remote rejected] master -> master (pre-receive hook declined)
error: failed to push some refs to 'https://git.heroku.com/scumbotfin.git'

答案 4 :(得分:0)

我确实没有看到您的用例,但是我认为此代码窃听器应该对您有用。这个想法是抛出一个异常,而不是返回一个null的可选orElse。您可以实现如下代码:

protected String toCombinedString(SomeClass shipment) {
   try {
        String prefix = ofNullable(shipment)
                .map(SomeClass::getBill)
                .map(Bill::getPrefixString)
                .orElseThrow(NullPointerException::new));

        String number = ofNullable(shipment)
                .map(SomeClass::getBill)
                .map(Bill::getNumberString)
                .orElseThrow(NullPointerException::new));
        .....

        return Stream.of(prefix, number, prefix1, number1....)
                .reduce((a, b) -> a + "-" + b);
   } catch(NullPointerException e) {
        return null;
   }
}

为了清楚起见,您也可以将try捕获包装在该函数之外,但是这种逻辑应该可以工作,并且可以在执行过程中在遇到的第一个空值处停止执行,从而优化性能。

答案 5 :(得分:0)

如果与问题的第一个版本一样只有两个字符串,则使用三元运算是解决问题的更有效方法: return prefix == null || number == null ? null : prefix + "-" + number;

如果您有更多项目,请使用流:

boolean hasNull = Stream.of(prefix, num).anyMatch(Objects::isNull);

return hasNull ? null : Stream.of(prefix, num).collect(Collectors.joining("-"));