因此,我有一个ArrayList
自动生成的字符串。我想找到包含某些字符的第一个元素,否则,如果没有一个元素与此过滤器匹配,则应用另一个过滤器。换句话说,我想返回null
对象。
所以我写了这个lambda表达式:
str.stream()
.filter(s -> s.contains("q"))
.findFirst()
.orElseGet(() -> str.stream()
.filter(s -> s.contains("w"))
.findFirst()
.orElseGet(null))
但是,如果没有一个元素与这两个过滤器匹配,则将出现NullPointerException。如何获得类似return null
的内容?
答案 0 :(得分:6)
除非我缺少明显的内容,否则只需.orElse(null)
,而不是最后一个orElseGet
。 orElseGet
接受Supplier
,而您传递了一个null
,并在空引用上调用get()
,那么...
答案 1 :(得分:4)
问题是Optional::orElseGet(null)
,它接受Supplier<T>
并抛出NullPointerException
。
使用Optional::orElse(null)
,它接受T
,在您的情况下为String
。
以下代码有效:
List<String> str = Arrays.asList("a", "b", "c");
String output = str.stream()
.filter(s -> s.contains("q"))
.findFirst()
.orElseGet(() -> str.stream()
.filter(s -> s.contains("w"))
.findFirst()
.orElse(null)); // <-- HERE
System.out.println(output); // Prints null
或者,使用Optional::orElseGet(Supplier<? extends T> other)
返回null
。 Supplier
本身不能为null
:
.orElseGet(() -> null));
答案 2 :(得分:2)
orElseGet
期望Supplier
,您需要传递一个值,orElse
就是这种情况。
在这里我不会使用Stream API,一次迭代就可以解决问题:
String wString = null;
for (String s : str) {
if (s.contains("q")) return s;
if (s.contains("w") && wString == null) wString = s;
}
return wString;
答案 3 :(得分:1)
另一种更简单的方法:您可以过滤包含q
或w
的字符串,然后排序以首先移动包含q
的字符串,首先查找,如果可选为空,则返回null :
str.stream()
.filter(s -> s.contains("q") || s.contains("w"))
.sorted((s1, s2) -> s1.contains("q") ? -1 : 1 )
.findFirst()
.orElse(null);
.sorted((s1, s2) -> s1.contains("q") ? -1 : 1 )
将首先移动包含"q"
的字符串。由于仅对包含q
或w
的值进行了流过滤,因此返回null只会发生任何保留元素的情况。