小心 Java 可选方法
来源:
Dev.to根据 Oracle 的说法, Optional对象是“一个可能包含也可能不包含非空值的容器对象”。Optional首先出现在Java 8中,并已被SpringBoot团队在许多项目中使用。
Options最常见的用途是在 Spring Data 项目中。让我们看一下 JpaRepository 接口和示例方法。例如,我们有一个具有整数类型 Id 的
User对象,并且我们有一个 JpaRepository 。
@Repository
public interface IUserRepo extends JpaRepository<User, Integer>
{
Optional<User> findByUserName(String userName);
}
我们定义了一个方法,通过用户名查找用户并返回
User的
Optional。
便捷方式可选
许多方法中都包含可选,使我们能够编写干净且可读的代码。
然而,有一种方法会产生危险的意外行为。
认识 orElse 方法
根据 Oracle 文档:
public T orElse(T other)
如果有则返回该值,否则返回其他值。现在我们可以添加一个方法调用作为
orElse参数,如果
可选参数为空,该方法调用将运行,对吗?是的,这是正确的,但是如果我告诉你无论
Optional是否有值,它无论如何都会起作用怎么办?让我们检查:
@Test
public void orElseTest()
{
String result = Optional.of("hello").orElse(someMethod());
assertThat(result).isEqualTo("hello");
}
private String someMethod()
{
System.out.println("I am running !!");
return "hola";
}
测试成功,但是您会注意到控制台上打印了 “
我正在运行”这一行。
为什么会发生这种情况?
Java 运行一个方法来提供Else情况下将返回的值。
所以要小心!
如果orElse中的方法可能有副作用, 您必须小心,因为它仍然会运行。
该怎么办?
您可以使用
OrElseGet方法,该方法采用供应商方法来执行(如果
可选存在) 。
如何在 Java 中显示列表中的元素并对其求和
来源:
DZone 在这篇文章中,您将学习如何在 Java 中显示和汇总列表中的元素数量。映射列表中的项目
意味着该列表中的每个项目都将转换为不同的对象。对列表中的元素求和意味着该列表中的所有元素将组合成一个对象,该对象不一定与原始对象类型相同。假设我们有一个订单列表,每个订单都有一个产品列表。
record Order(String customer, List<Product> products) {
}
record Product(String brand, String modelName, BigDecimal price) {
}
如果您想知道订单清单上有多少钱,您会怎么做?对于每个订单,您将需要获取其中包含的产品列表,并且对于这些列表中的每个产品,您将需要获取其成本。之后,您需要将所有这些价格相加,这就是您得到结果的方式。将上面的内容转换为
Map /
Reduce时,您需要:
- 将每个订单与产品列表相匹配。
- 显示每种产品的价格。
- 通过将所有价格加在一起来总结所有价格。
那么让我们用 Java 来做:
public class OrderMapReducer {
public BigDecimal getTotal(List<Order> orders) {
return orders.stream()
.map(Order::products)
.flatMap(List::stream)
.map(Product::price)
.reduce(BigDecimal::add)
.orElse(BigDecimal.ZERO);
}
}
- 我们创建订单流。
- 我们将每个订单与其产品列表进行匹配。
- 我们将每个产品列表与流程进行匹配。请注意,我们必须在这里使用flatMap,否则我们最终会得到Stream <Stream <Product>>。
- 对于每种产品,我们都会显示其价格。
- 让我们总结一下所有的价格。
- 如果订单列表为空,则返回零。
就这样!现在我们可以创建一个测试来确保一切都按预期工作。
@Test
void getTotalPrice() {
List<Order> orders = createOrders();
OrderMapReducer orderMapReducer = new OrderMapReducer();
assertEquals(new BigDecimal(17800), orderMapReducer.getTotal(orders));
}
private static List<Order> createOrders() {
var strato = new Product("Fender", "Stratocaster", new BigDecimal(3500));
var sg = new Product("Gibson", "SG", new BigDecimal(4800));
var lesPaul = new Product("Gibson", "Les Paul", new BigDecimal(4500));
var rr = new Product("Jackson", "RR", new BigDecimal(5000));
return List.of(
new Order("David Gilmour", List.of(strato)),
new Order("Toni Iommi", List.of(sg)),
new Order("Randy Rhoads", List.of(lesPaul, rr))
);
}
正如您所看到的,Map 和Reduce 在您需要从
Collection中提取信息的情况下很有帮助。
GO TO FULL VERSION