Uwolnij moc Java 8: The Ultimate Guide to the Key Features

Feb 16 2023
Java 8 wprowadziła kilka nowych funkcji, które pomogły uczynić ją bardziej wszechstronną i elastyczną. Funkcja Java 8 umożliwia programowanie funkcjonalne.
Jawa 8

Java 8 wprowadziła kilka nowych funkcji, które pomogły uczynić ją bardziej wszechstronną i elastyczną. Funkcja Java 8 umożliwia programowanie funkcjonalne . Oto niektóre z kluczowych cech Javy 8:

  1. Wyrażenia lambda
  2. Interfejsy funkcjonalne
  3. Strumień API
  4. Metody domyślne
  5. Referencje metody
  6. Opcjonalny
  7. Interfejs API daty/godziny

1. Wyrażenia lambda

Java 8 | Wyrażenia lambda

Za pomocą wyrażeń lambda możemy przedstawić blok kodu, który można później wykonać.

Wyrażenia lambda służą do definiowania funkcji anonimowych , które mogą być przekazywane jako argumenty metod lub mogą być zwracane z metod, tak jak inne obiekty.

Składnia wyrażenia lambda:

(parameters) -> { statements };

Przykłady:

(i) brak argumentów

()-> System.out.println("lambda expression with no arguments");

// lambda expression with one argument
(a) -> System.out.println(String.format("Value of a is: %s", a);

// lambda expression with multiple arguments
(a, b) -> a + b;

// also argument type can be provided explicitely
(Integer a, Integer b) -> a + b;

(Integer a, Integer b) -> {  // parentheses needed for multiple statements
    System.out.println(String.format("Returning maximum from %s and %s", a, b));
    return (a > b) a : b;
};

// functional interface, we will see below in detail
interface MaxFinder {
    int findMax(int a, int b);
}

public class LambdaExpressionExample {
    public static void main(String[] args) {
        // return maximum of two numbers using lambda expression
        MaxFinder maxFinder = (a, b) -> (a > b) ? a : b;
        
        System.out.println(maxFinder.findMax(5, 10));
        System.out.println(maxFinder.findMax(15, 5));
    }
}

Wyjście

Zobaczmy teraz, jak można użyć wyrażenia lambda z pętlą forEach :

public class LambdaExpressionExample {
  public static void main(String[] args) {
        List<Integer> nums = new ArrayList<>();
        nums.add(1);
        nums.add(2);
        nums.add(3);
        nums.add(4);
        nums.forEach(num -> System.out.println(String.format("Square of %s is %s", num, num * num)));
    }
}

Wyjście

2. Interfejsy funkcjonalne

Java 8 | Interfejsy funkcjonalne

Interfejs, który ma dokładnie jedną metodę abstrakcyjną, nazywany jest interfejsem funkcjonalnym , a także nazywany jest interfejsem pojedynczej metody abstrakcyjnej (interfejsy SAM) .

Funkcjonalne interfejsy są podstawą wyrażeń Lambda i umożliwiają pisanie zwięzłego i wyrazistego kodu, eliminując potrzebę anonimowych klas wewnętrznych.

Java 8 zapewnia wiele wbudowanych interfejsów funkcjonalnych, niektóre z nich to Predicate , Function , Consumer i Supplier .

Możesz odwołać się do powyższego prostego przykładu, w którym zdefiniowaliśmy funkcjonalny interfejs MaxFinder .

Adnotacja @FunctionalInterface służy do reprezentowania funkcjonalnego interfejsu.

(i) Predykat

Interfejs predykatów ma pojedynczą metodę abstrakcyjną test(T t) , która przyjmuje pojedynczy argument i zwraca wartość logiczną .

Zwykle jest używany do filtrowania wartości lub do sprawdzania, czy wartość spełnia warunek.

T : typ argumentu wejściowego metody

Oto przykład użycia predykatu :

Predicate<Integer> isEligibleForVoting = (age) -> age >= 18;
boolean eligible = isEligibleForVoting.test(22); // true

Interfejs funkcji ma jedną abstrakcyjną metodę apply(T t) , która przyjmuje jeden argument i zwraca obiekt .

Zasadniczo jest używany do przekształcania lub mapowania wartości z jednego typu na inny.

Oto przykład użycia funkcji :

Function<Integer, Integer> findSquare = (num) -> (num*num);
int square = findSquare.apply(5); // 25

Interfejs konsumenta ma jedną abstrakcyjną metodę accept(T t) , która przyjmuje pojedynczy argument i nie zwraca żadnego wyniku .

Zwykle służy do wykonywania efektów ubocznych, takich jak drukowanie lub logowanie .

Oto przykład użycia Consumer :

Consumer<String> printValue = (x) -> System.out.println(x);
printValue.accept("Java 8 features!"); // prints "Java 8 features!"

Interfejs dostawcy ma jedną abstrakcyjną metodę get(), która nie przyjmuje żadnych argumentów i zwraca wynik .

Zwykle jest używany do leniwej inicjalizacji lub do generowania losowych wartości.

Oto przykład użycia dostawcy:

Supplier<Integer> getRandomInteger = () -> (int) (Math.random() * 500);
int randomInteger = getRandomInteger.get(); // random integer between 0 and 500

public class FunctionalInterfacesExample {

    public static void main(String[] args) {
        // Using Predicate functional interface
        Predicate<Integer> isEligibleForVoting = (age) -> age >= 18;
        boolean eligible = isEligibleForVoting.test(22); // true
        System.out.println(String.format("Eligible for voting: %s", eligible));
        
        // Using Function functional interface
        Function<Integer, Integer> findSquare = (num) -> (num * num);
        int square = findSquare.apply(5); // 25
        System.out.println(String.format("Square of 5: %s", square));
        
        // Using Consumer functional interface
        Consumer<String> printValue = (val) -> System.out.println(val);
        printValue.accept("Java 8 features!"); // prints "Java 8 features!"
        
        // Using Supplier functional interface
        Supplier<Integer> getRandomInteger = () -> (int) (Math.random() * 500);
        int randomInteger = getRandomInteger.get(); // random integer between 0 and 500
        System.out.println(String.format("Random number: %s", randomInteger));
    }

}

Wyjście

3. Strumieniowe API

Java 8 | Strumień API

Java 8 Stream API to potężne narzędzie do przetwarzania kolekcji danych.

Za pomocą Stream API złożone zadania manipulacji danymi można wykonywać w bardziej zwięzły i wyrazisty sposób niż w przypadku instrukcji warunkowych i tradycyjnych pętli.

Strumień to uporządkowana sekwencja elementów , które mogą być przetwarzane sekwencyjnie lub równolegle .

Za pomocą funkcjonalnych interfejsów i metod możemy tworzyć , przekształcać i przetwarzać strumienie.

Strumień kolekcji można utworzyć za pomocą metody stream() .

Streams API to nowy dodatek do Java Collections Framework, który zapewnia deklaratywny sposób przetwarzania kolekcji obiektów. Strumienie umożliwiają wykonywanie różnych operacji, takich jak filtrowanie , mapowanie i zmniejszanie na kolekcjach obiektów w bardziej zwięzły i czytelny sposób niż tradycyjne pętle for.

Stream API składa się z trzech typów operacji:

(i) Operacje pośrednie:

Operacje pośrednie służą do przekształcania lub filtrowania elementów strumienia.

Zwracają nowy strumień , który dalej może być przetwarzany przez operacje pośrednie lub końcowe .

Najczęściej stosowanymi operacjami pośrednimi są:

  • filter() : służy do filtrowania wartości na podstawie warunku
  • sorted() : służy do sortowania elementów
  • different() : służy do znajdowania odrębnych elementów
  • map() : służy do mapowania wartości z jednego typu na inny

Operacje terminalowe służą do generowania końcowego wyniku ze strumienia.

Są one wywoływane po wszystkich operacjach pośrednich , które zostały zastosowane do strumienia.

Najczęściej używane operacje terminalowe to:

  • collect() : używany do zwrócenia wyniku operacji pośrednich
  • reduce() : służy do redukcji elementów strumienia do jednego elementu.
  • forEach() : używany do iteracji przez każdy element w strumieniu
  • count() : zwraca liczbę elementów w tym strumieniu

Operacje zwarcia służą do wczesnego uzyskania wyniku, bez przetwarzania całego strumienia.

Operacje pośrednie i terminalowe strumienia Java 8 mogą powodować zwarcie.

Najczęściej używane operacje terminalowe to:

  • limit() : używany do zwracania strumienia, gdy tylko osiągnie zadaną wartość graniczną
  • anyMatch() : używana do sprawdzania, czy jakiekolwiek elementy tego strumienia pasują do podanego predykatu.
  • findFirst() : zwraca Opcjonalny opis pierwszego elementu strumienia lub pusty Opcjonalny, jeśli strumień jest pusty
  • findAny() : zwraca Opcjonalne opisujące jakiś element strumienia lub puste Opcjonalne, jeśli strumień jest pusty.

public class StreamAPIExample {

    public static void main(String[] args) {
        List<Integer> nums = Arrays.asList(3, 1, 4, 2, 6, 8, 5, 7);
        System.out.print("Given numbers list: ");
        nums.forEach(num -> System.out.print(String.format("%s, ", num)));
        System.out.println();
        
        // sort list of numbers
        List<Integer> sortedNums = nums.stream().sorted().collect(Collectors.toList());
        System.out.print("Sorted numbers are: ");
        sortedNums.forEach(num -> System.out.print(String.format("%s, ", num)));
        System.out.println();
        
        // filter all numbers less than 6
        List<Integer> filteredNums = nums.stream()
                .filter(i -> i < 6)
                .collect(Collectors.toList());
        System.out.print("Numbers less then 5 are: ");
        filteredNums.forEach(num -> System.out.print(String.format("%s, ", num)));
        System.out.println();
        
        // odd numbers
        long oddNumsCount = nums.stream()
                .filter(i -> i % 2 == 1).count();
        System.out.println(String.format("Total odd numbers are: %s", oddNumsCount));
        
        // print first 2 even numbers found from list while iterating stream
        System.out.print("first 2 even numbers found from list while iterating stream: ");
        nums.stream()
                .filter(num -> num % 2 == 0)
                .limit(2)
                .forEach(num -> System.out.print(String.format("%s, ", num)));
        System.out.println();
        
        // find squares of numbers
        List<Integer> squares = nums.stream()
                .map(num -> (num * num))
                .collect(Collectors.toList());
        System.out.print("Squares of numbers are: ");
        squares.forEach(square -> System.out.print(String.format("%s, ", square)));
    }

}

Wyjście

Dziękujemy za przeczytanie, mam nadzieję, że ta historia pomogła ci w nauce funkcji Java 8.

Proszę śledzić , jeśli podoba Ci się artykuł.

Zapisz się , aby być na bieżąco z nadchodzącymi artykułami.