JavaRush /Java Blog /Random EN /Coffee break #97. Be careful with the Java Optional metho...

Coffee break #97. Be careful with the Java Optional method. How to display and sum elements from a list in Java

Published in the Random EN group

Be careful with the Java Optional method

Source: Dev.to According to Oracle, an OptionalCoffee break #97.  Be careful with the Java Optional method.  How to display and sum elements from a list in Java - 1 object is “a container object that may or may not contain a non-null value.” Optional first appeared in Java 8 and has been used by the SpringBoot team in many projects. The most common use of Optionals is in a Spring Data project. Let's look at the JpaRepository interface and an example method. For example, we have a User object with an integer type Id and we have a JpaRepository for it.
@Repository
public interface IUserRepo extends JpaRepository<User, Integer>
{
    Optional<User> findByUserName(String userName);
}
We've defined a method that looks up a user by their name and returns an Optional for User .

Convenient Methods Optional

Optional is included in many methods that allow us to write clean and readable code. However, there is one method with dangerously unexpected behavior.

Meet the orElse method

According to Oracle documentation:
public T orElse(T other)
Return the value if there is one, otherwise return something else. Now we can add a method call as an orElse parameter that will run if the Optional parameter is empty, right? Yes, that's correct, but what if I told you that it will work anyway, regardless of whether there is a value in Optional or not. Let's check:
@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";
}
The test was successful, but you will notice that the line “ I am running ” is printed on the console.

Why is this happening?

Java runs a method to provide the value that will be returned in the case of Else .

So be careful!

You have to be careful if a method inside orElse might have a side effect because it will still be run.

What to do?

You can use the OrElseGet method , which takes a supplier method to execute if Optional exists .

How to display and sum elements from a list in Java

Source: DZone In this post, you will learn how to display and summarize the number of elements from a list in Java. Mapping items from a List means that each item in that list will be converted to a different object. Summing elements from a list means that all elements from that list will be combined into one object, which is not necessarily the same type as the original one. Let's say we have a list of orders, and each order has a list of products.
record Order(String customer, List<Product> products) {
}

record Product(String brand, String modelName, BigDecimal price) {
}
What would you do if you wanted to know how much money was coming from an order list? For each order, you will need to get a list of the products present in it, and for each product in these lists, you will need to get its cost. After that, you need to sum up all these prices, and this is how you get the result. When translating the above to Map / Reduce you need:
  1. Match each order with a product list.
  2. Display the price for each product.
  3. Sum up all prices by adding them together.
So let's do it in Java:
public class OrderMapReducer {
    public BigDecimal getTotal(List<Order> orders) {
        return orders.stream() // 1
                     .map(Order::products) // 2
                     .flatMap(List::stream) // 3
                     .map(Product::price) // 4
                     .reduce(BigDecimal::add) // 5
                     .orElse(BigDecimal.ZERO); // 6
    }
}
  1. We create a flow of orders.
  2. We match each order with its product list.
  3. We match each product list with a flow. Note that we had to use flatMap here , otherwise we would end up with Stream <Stream <Product>> .
  4. For each product we display its price.
  5. Let's sum up all the prices.
  6. If the Order List is empty, return zero.
That's all! Now we can create a test to make sure everything is working as expected.
@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))
    );
}
As you can see, Map and Reduce helps in cases where you need to extract information from a Collection .
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION