#### Funkcje czyste

Prosta funkcja do tworzenia powitania dla instacji `User`:

```java
public String buildGreeting(User user)
```

Ten publiczny kontrakt nie wskazuje wszystkich swoich zalenoci:

```java
public String buildGreeting(User user) {
    String greeting;
    if (LocalTime.now().getHour() < 12) {
        greeting = "Dzie dobry,";
    } else {
        greeting = "Witaj,"
    }

    return String.format("%s, %s", greeting, user.name());
}
```

Poprawiona sygnatura metody zawielaaby aktualny czas:

```java
public String buildGreeting(User user, LocalTime time)
```

Teraz funkcja jest czysta i generuje swoje dane wyjciowe wycznie na podstawie swoich argumentw.


#### Czyste metody obiektowe

Python sprawia, e bardziej widoczne jest to, i czci sygnatury metody jest sama bieca instancja w formie `self`:

```python
class User:

  name = ''

  def __init__(self, name):
    self.name = name 

  def buildGreeting(self, time):
    # ...
```

#### Wyraenia lepsze ni instrukcje

Poprzedni metod `buildGreeting` mona ulepszy przez przekonwertowanie instrukcji `if-else` na wyraenie:

```java
public String buildGreeting(User user, LocalTime time) {

    String greeting = time.getHour() < 12 ? "Dzie dobry,"
                                          : "Dzie dobry,";

    return String.format("%s, %s", greeting, user.name());
}
```

### Funkcyjne przetwarzanie danych za pomoc wzorca Mapowanie, Filtrowanie, Redukcja

Gdy ma to zastosowanie, typowe przetwarzenie danych -- iterowanie, filtrowanie, gromadzenie -- moe wykorzystywa strumienie:

```java
List<User> usersToNotify = new ArrayList<>();

for (var users : availableUsers) {

    if (user.hasValidSubscription()) {
        continue;
    }

    usersToNotify.add(user);
}

notify(usersToNotify);
```

Potok strumieniony sprawia, e kod jest bardziej zwizy i zrozumiay:

```java
List<User> usersToNotify = availableUsers.stream()
                                         .filter(User::hasValidSubscription)
                                         .toList();

notify(usersToNotify);
```

### Budowanie funkcyjnych pomostw

#### Uycie retroaktywnych interfejsw funkcynych

Wiele typw, ktre byy dostpne przed wydaniem Javy 8, to interfejsy funkcyjne, ktre mog by uywane jako lambdy:

```java
// KLASA ANONIMOWA

users.sort(new Comparator<User>() {

    @Override
    public int compare(User lhs, User rhs) {
        return lhs.email().compareTo(rhs.email());
    }
});


// JAKO LAMBDA

users.sort((lhs, rhs) -> lhs.email().compareTo(rhs.email()));


// JAKO REFERENCJA DO METODY

users.sort(Comparator.comparing(User::email));
```

#### Metody wytwrcze wyrae lambda dla typowych operacji

Typy mog zapewnia lambdy dla bardziej zwizych funkcji wyszego rzdu:

```java
public class ProductCategory {

    public String localizedDescription(Locale locale) {
        return "...";
    }

    // METODA WYTWRCZA LAMBDY
    public static Function<ProductCategory, String> localizedDescriptionMapper(Locale locale) {
        return category -> category.localizedDescription(locale);
    }
}

var locale = Locale.GERMAN;

List<ProductCategory> categories = List.of(...);

// BEZPOREDNIE LAMBDY

List<String> descriptionsViaExplicitLambdas =
    categories.stream()
              .map(category -> category.localizedDescription(locale))
              .toList();

// METODA WYTWRCZA LAMBD

List<String> descriptionsViaLambdaFactory =
    categories.stream()
              .map(ProductCategory.localizedDescriptionMapper(locale))
              .toList();
```

#### Bezporednie implementowanie interfejsw funkcyjnych

Interfejsy mog rozszerza typowe interfejsy funkcyjne, aby mona byo zastosowa je w strumieniu opcyjnych operacji potoku:

```java
interface VideoConverterJob extends Function<Path, Path> {

  Path convert(Path sourceFile);

  default Path apply(Path sourceFile) {
        return convert(sourceFile);
  }
}
```

#### Funkcyjna obsuga null za pomoc typw Optional

Typy Optional doskonale nadaj si do usprawnienia przeprowadzania wielu operacji na wartoci, ktra moe by `null`:

```java
public Optional<User> tryLoadUser(long id) {
  // ...
}

boolean isAdminUser =
  tryLoadUser(23L).map(User::getPermissions)
                  .filter(Predicate.not(Permissions::isEmpty))
                  .map(Permissions::getGroup)
                  .flatMap(Group::getAdmin)
                  .map(User::isActive)
                  .orElse(Boolean.FALSE);
```

Jednak nie kad warto `null` naley obsugiwa za pomoc typw Optional:

```java
// LE: opakowywanie wartoci dla prostego wyszukiwania

var nicknameOptional = Optional.ofNullable(customer.getNickname())
                               .orElse("Anonymous");


// LEPIEJ: prostsze kontrole null

var nicknameTernary = customer.getNickname() != null ? customer.getNickname()
                                                     : "Anonymous";
```

Zamiast operatora trjargumentowego zasze moe rwnie uy `Objects.requireNonNullElse`:

```java
var nickname = Objects.requireNonNullElse(customer.getNickname(), "Anonymous");

var nicknameWithSupplier = Objects.requireNonNullElse(customer.getNickname(),
                                                      () -> "Anonymous");
```

