Zachowaj ostrożność, stosując metodę opcjonalną Java
Źródło:
Dev.to Według Oracle obiekt
opcjonalny to „obiekt kontenera, który może zawierać wartość różną od null lub nie”. Opcja opcjonalna pojawiła się po raz pierwszy w Javie 8 i była używana przez zespół SpringBoot w wielu projektach. Najczęstszym zastosowaniem
opcji jest projekt Spring Data. Przyjrzyjmy się interfejsowi JpaRepository i przykładowej metodzie. Na przykład mamy obiekt
User z identyfikatorem typu całkowitego i mamy dla niego JpaRepository.
@Repository
public interface IUserRepo extends JpaRepository<User, Integer>
{
Optional<User> findByUserName(String userName);
}
Zdefiniowaliśmy metodę, która wyszukuje użytkownika według jego nazwy i zwraca
opcję Option dla
User .
Wygodne metody Opcjonalne
Opcjonalne jest zawarte w wielu metodach, które pozwalają nam pisać czysty i czytelny kod.
- mapa(..).albo(...)
- mapa(...).lub Inaczej(...)
- pełną listę można znaleźć w dokumentacji Oracle .
Istnieje jednak jedna metoda, która charakteryzuje się niebezpiecznie nieoczekiwanym zachowaniem.
Poznaj metodę orElse
Według dokumentacji Oracle:
public T orElse(T other)
Zwróć wartość, jeśli taka istnieje, w przeciwnym razie zwróć coś innego. Teraz możemy dodać wywołanie metody jako parametr
orElse , które zostanie uruchomione, jeśli parametr
Opcjonalny jest pusty, prawda? Tak, to prawda, ale co jeśli powiem ci, że to i tak zadziała, niezależnie od tego, czy w
Opcjonalnym jest wartość , czy nie. Sprawdźmy:
@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";
}
Test zakończył się pomyślnie, ale zauważysz, że na konsoli wyświetla się wiersz „
Uruchamiam ”.
Dlaczego to się dzieje?
Java uruchamia metodę dostarczającą wartość, która zostanie zwrócona w przypadku
Else .
Więc uważaj!
Musisz zachować ostrożność, jeśli metoda wewnątrz
orElse może wywołać efekt uboczny, ponieważ nadal będzie wykonywana.
Co robić?
Można użyć metody
OrElseGet , która pobiera metodę dostawcy do wykonania, jeśli istnieje
Option .
Jak wyświetlać i sumować elementy z listy w Javie
Źródło:
DZone W tym poście dowiesz się, jak wyświetlić i podsumować liczbę elementów z listy w Javie. Mapowanie elementów z listy
oznacza , że każdy element na tej liście zostanie przekonwertowany na inny obiekt. Sumowanie elementów z listy oznacza, że wszystkie elementy z tej listy zostaną połączone w jeden obiekt, który niekoniecznie jest tego samego typu co obiekt pierwotny. Załóżmy, że mamy listę zamówień, a każde zamówienie ma listę produktów.
record Order(String customer, List<Product> products) {
}
record Product(String brand, String modelName, BigDecimal price) {
}
Co byś zrobił, gdybyś chciał wiedzieć, ile pieniędzy pochodzi z listy zamówień? Dla każdego zamówienia będziesz musiał uzyskać listę produktów znajdujących się w nim, a dla każdego produktu na tych listach będziesz musiał poznać jego koszt. Następnie należy zsumować wszystkie te ceny i tak otrzymujemy wynik. Do tłumaczenia powyższego na
Map /
Reduce potrzebne będą:
- Do każdego zamówienia dopasuj listę produktów.
- Wyświetl cenę każdego produktu.
- Zsumuj wszystkie ceny, dodając je do siebie.
Zróbmy to w Javie:
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);
}
}
- Tworzymy przepływ zamówień.
- Do każdego zamówienia dopasowujemy listę produktów.
- Do każdej listy produktów dopasowujemy przepływ. Zauważ, że musieliśmy tutaj użyć flatMap , w przeciwnym razie otrzymalibyśmy Stream <Stream <Product>> .
- Przy każdym produkcie podajemy jego cenę.
- Podsumujmy wszystkie ceny.
- Jeśli lista zamówień jest pusta, zwróć zero.
To wszystko! Teraz możemy utworzyć test, aby upewnić się, że wszystko działa zgodnie z oczekiwaniami.
@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))
);
}
Jak widać, Map i Redukcja pomagają w przypadkach, gdy trzeba wyodrębnić informacje z
kolekcji .
GO TO FULL VERSION