如何链式调用Optional的ifPresent方法?
如何链式处理Optional的多次消费需求
假设我们持有一个Optional对象,需要对其包含的元素执行多次消费操作,目前常见的几种实现方式各有局限:
现有方案及问题
保存到变量后多次调用ifPresent
需要额外声明变量,代码不够简洁:Optional<Animal> optionalAnimal = animalService.getAllAnimals().findFirst(); optionalAnimal.ifPresent(Animal::eat); optionalAnimal.ifPresent(Animal::drink);单个ifPresent中合并多个操作
无法复用独立的方法引用,只能将操作写在lambda块中:animalService.getAllAnimals().findFirst() .ifPresent(animal -> { animal.drink(); animal.eat(); });修改目标类方法使其返回自身(配合map链式调用)
语义上不符合方法本身的职责,且无法控制所有目标类(比如final类无法修改或继承):animalService.getAllAnimals().findFirst() .map(Animal::drink) .ifPresent(Animal::eat);
由于Optional本身是final类,无法通过继承扩展ifPresent方法使其返回自身,我们期望能实现类似以下的链式调用写法:
animalService.getAllAnimals().findFirst() .ifPresent(Animal::drink) .ifPresent(Animal::eat);
可行解决方案
方案1:利用Stream的peek方法(Java 9+)
借助Optional的stream()方法将其转换为单元素流,通过peek执行消费操作,最后转回Optional:
animalService.getAllAnimals().findFirst() .stream() .peek(Animal::drink) .peek(Animal::eat) .findFirst();
如果是Java 8环境,可使用Stream.ofNullable替代:
Stream.ofNullable(animalService.getAllAnimals().findFirst().orElse(null)) .peek(Animal::drink) .peek(Animal::eat) .findFirst();
方案2:自定义静态工具类实现peek逻辑
编写一个静态工具方法,执行消费后返回原Optional,实现链式调用:
public class OptionalUtils { public static <T> Optional<T> peek(Optional<T> optional, Consumer<? super T> consumer) { optional.ifPresent(consumer); return optional; } }
使用时通过静态导入简化代码:
import static com.example.OptionalUtils.peek; peek(animalService.getAllAnimals().findFirst(), Animal::drink) .ifPresent(Animal::eat);
内容的提问来源于stack exchange,提问作者Dario Viva
相关产品推荐
相关产品推荐

