在Java 8中,我想对一个Optional对象做一些事情,如果它存在,并做另一件事,如果它不存在.
if (opt.isPresent()) {
System.out.println("found");
} else {
System.out.println("Not found");
}
Run Code Online (Sandbox Code Playgroud)
但这不是一种"功能风格".
Optional有一个ifPresent()方法,但我无法链接一个orElse()方法.
因此,我不能写:
opt.ifPresent( x -> System.out.println("found " + x))
.orElse( System.out.println("NOT FOUND"));
Run Code Online (Sandbox Code Playgroud)
在回复@assylias时,我认为不适Optional.map()用于以下情况:
opt.map( o -> {
System.out.println("while opt is present...");
o.setProperty(xxx);
dao.update(o);
return null;
}).orElseGet( () -> {
System.out.println("create new obj");
dao.save(new obj);
return null;
});
Run Code Online (Sandbox Code Playgroud)
在这种情况下,当opt存在时,我更新其属性并保存到数据库.当它不可用时,我创建一个新的obj并保存到数据库.
请注意我必须返回的两个lambda null.
但是当opt存在时,两个lambdas都将被执行.obj将更新,并将新对象保存到数据库.这是因为return null在第一个lambda中.并且orElseGet()将继续执行.
寻找一种链接选项的方法,以便返回第一个存在的选项.如果没有,Optional.empty()则应退回.
假设我有几个像这样的方法:
Optional<String> find1()
Run Code Online (Sandbox Code Playgroud)
我想把它们链起来:
Optional<String> result = find1().orElse( this::find2 ).orElse( this::find3 );
Run Code Online (Sandbox Code Playgroud)
但当然这不起作用,因为orElse期望一个值,并orElseGet期望一个Supplier.
我有两个java.util.Optional实例,我想得到一个Optional:
是否有直接的方法来做到这一点,即是否已经有一些API来做到这一点?
以下表达式会这样做,但我必须提到第一个可选的两次:
firstOptional.isPresent() ? firstOptional : secondOptional
Run Code Online (Sandbox Code Playgroud)
这正是com.google.common.base.Optional.or()如此,但Java 8的API中不存在该方法.
aioobe接受的答案列出了一些替代方法来克服这种遗漏OptionalAPI的权利,在这种情况下必须计算这样的值(这回答了我的问题).我现在选择在我的代码库中添加一个实用程序函数:
public static <T> Optional<T> or(Optional<T> a, Optional<T> b) {
if (a.isPresent())
return a;
else
return b;
}
Run Code Online (Sandbox Code Playgroud) 我正在将一些代码移动到java8,尝试(有时强迫自己)使用stream和lambdas,我对它们感到不舒服.
我在类中有一些验证业务对象的方法.每个方法看起来都像
Optional<Fail> validate1(BusinessObject bo)
Run Code Online (Sandbox Code Playgroud)
其中Fail是以某种方式描述错误的枚举,如果没有错误,则该方法返回Optional.empty().我不需要收集所有错误,但返回第一个错误,而不执行以下验证.
我正在做的是
//first convert methods to suppliers
Supplier<Optional<Fail>> validate1= () -> validate1(bo);
Supplier<Optional<Fail>> validate2= () -> validate2(bo);
Supplier<Optional<Fail>> validate3= () -> validate3(bo);
//then some stream magic
return Stream.of(validate1, validate2, validate3)
.map(Supplier::get)
.filter(f -> f.isPresent())
.findFirst()
.orElse(Optional.empty()); //without the orElse, no error would return
// Optional(Optional.empty())
// instead of Optional.empty()
Run Code Online (Sandbox Code Playgroud)
它工作,它完成工作,它不执行不必要的方法,它是清晰的(如果Optional.orElse被命名为getOrElse,它会更清晰,但这是我无法实现的).我想要找出的是,如果这是一个合理的方式来做我想要的,如果这个代码被认为是'好风格'或'惯用java8',或者我误用Stream或Optional,或者遗漏了一些明显的东西.
如果它们都是空的,那么返回第一个非空的Optional或者一个空的Optional的想法看起来很普遍,以为有一个正式的方法可以做到这一点,在我脑后的东西是大喊"Monads!",但我的无知Haskell几乎是完美的,所以我不知道.
我有几个方法,每个方法返回一个可选的字符串.我如何组合,以便java调用每个方法,直到找到结果?
我想最终得到这样的东西,但没有orElseFlatMap()方法:
import java.util.Optional;
public class OptionalCascade {
public static void main(String[] args) {
Optional<String> result =
// try to get a result with method A
methodA()
// if method A did not return anything, then try method B
.orElseFlatMap(methodB());
}
static Optional<String> methodA() {
return Optional.empty();
}
static Optional<String> methodB() {
return Optional.empty();
}
}
Run Code Online (Sandbox Code Playgroud) 我有N个列表从存储库返回数据.我想返回这三个列表中的第一个非空(每个列表执行不同的SQL来获取数据).
问题是我想懒得这样做,所以如果我已经找到了可接受的结果,我就不需要在数据库上执行SQL.我的代码是(修改过的)
@Override
public List<Something> dataService(Data data) {
return firstNonEmptyList(repository.getDataWayOne(data.getParameter()),
repository.getDataWayTwo(data.getParameter()),
repository.getDataWayThree(data.getParameter().getAcessoryParameter())
Collections.singletonList(repository.getDefaultData(data.getParameter()));
}
@SafeVarargs
private final List<Something> firstNonEmptyList(List<Something>... lists) {
for (List<Something> list : lists) {
if (!list.isEmpty()) {
return list;
}
}
return null;
}
Run Code Online (Sandbox Code Playgroud)
这有效,但它不是懒惰的.有任何想法吗?
假设我有这个方法
public Optional<String> validateAndReturnErrorMessage(SomeEcommerceSale s) {
Optional<String> errorWithItem = validateItem(s.getItem());
if (errorWithItem.isPresent()) return errorWithItem;
Optional<String> errorWithPayment = validatePayment(s.getPayment());
if (errorWithPayment.isPresent()) return errorWithPayment;
// assume I have several other cases like the 2 above
return Optional.empty(); // meaning there were no errors
Run Code Online (Sandbox Code Playgroud)
我的问题是,由于OrElse and OrElseGetreturn<T>而不是Optional<T>,是否有一种本地方法可以将其重写为更实用的方式,而无需几个松散耦合的 return 语句?
编辑
我想一一检查验证,因为它们是外部且沉重的。这样,我只会调用必要的
我有这个Java 8代码:
public Optional<User> getUser(String id) {
Optional<User> userFromCache = cache.getUser(id);
if (userFromCache.isPresent()) {
return userFromCache;
}
return repository.getUser(id);
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,但我想知道如何将呼叫链接到不使用if.我试过orElseGet但它不允许返回另一个Optional<User>但是User.
我想要这样的东西:
Optional<User> userFromCache = cache.getUser(id)
.orElseGet(() -> repository.getUser(id));
Run Code Online (Sandbox Code Playgroud) 我想在找到第一个值时终止流的执行.但是,当我在下面运行代码时,它会显示即使第一个方法存在值,也会调用两个方法.
public static void main(String[] args) {
Optional<String> s = Stream.of(first(), second())
.filter(Optional::isPresent)
.findFirst()
.flatMap(Function.identity());
System.out.println(s.get());
}
private static Optional<String> first() {
System.out.println("first");
return Optional.of("someValue");
}
private static Optional<String> second() {
System.out.println("second");
return Optional.empty();
}
Run Code Online (Sandbox Code Playgroud)
我在文档中检查了:
如果存在值,则返回{@code true},否则返回{@code false}.
返回描述此流的第一个元素的{@link Optional},如果流为空,则返回空的{@code Optional}.如果流没有遭遇顺序,则可以返回任何元素.
所以它遇到的第一个条件,第二个条件似乎也满足,因为它返回:
first
second
someValue
Run Code Online (Sandbox Code Playgroud)
如果第一个值存在,如何退出执行,而不执行第二个方法?
这是一个具有多个可能值的Guava可选项.
long numberToUse = Long.parseLong(Optional
.ofNullable(System.getenv(ENV_VAR))
.or(Optional.ofNullable(System.getProperty(PROP_VAR)))
.or("15"));
Run Code Online (Sandbox Code Playgroud)
如何将其转换为干净的Java 8语法?