1. Nowość w Javie 8: Programowanie funkcyjne

Wraz z wydaniem Java 8 wprowadzono potężną obsługę programowania funkcjonalnego . Można nawet powiedzieć o długo wyczekiwanym wsparciu dla programowania funkcyjnego. Kod zaczął być pisany szybciej, chociaż trudniej go było odczytać 🙂

Przed nauką programowania funkcyjnego w Javie zalecamy dobre zrozumienie trzech rzeczy:

  1. OOP, dziedziczenie i interfejsy ( poziomy 1-2 zadania Java Core ).
  2. Domyślna implementacja metod w .
  3. Klasy wewnętrzne i anonimowe .

Dobrą wiadomością jest to, że nie wiedząc tego wszystkiego, możesz korzystać z wielu funkcji programowania funkcyjnego w Javie. Zła wiadomość jest taka, że ​​już teraz trudno jest dokładnie zrozumieć, jak wszystko działa i jak wszystko działa bez tych samych wewnętrznych klas anonimowych.

W najbliższych wykładach skupimy się na tym, jak łatwo i prosto można korzystać z funkcji programowania funkcyjnego w Javie, bez głębokiego zrozumienia, jak to działa.

Zrozumienie wszystkich niuansów programowania funkcjonalnego w Javie zajmuje miesiące. Czytania takiego kodu można nauczyć się w kilka godzin. Sugerujemy więc zacząć od małego. Tak, nawet z tych samych strumieni wejścia-wyjścia.


2. Wątki I/O: łańcuchy wątków

Pamiętasz, jak kiedyś studiowałeś strumienie wejścia-wyjścia: InputStream, OutputStream, Reader, Writeritd.?

Istniały klasy strumieni, które odczytują dane ze źródeł danych , takich jak FileInputSteam, oraz pośrednie strumienie danych, które odczytują dane z innych strumieni, takich InputStreamReaderjak BufferedReader.

Strumienie te mogłyby być zorganizowane w łańcuchy przetwarzania danych. Na przykład tak:

FileInputStream input = new FileInputStream("c:\\readme.txt");
InputStreamReader reader = new InputStreamReader(input);
BufferedReader buff = new BufferedReader(reader);

String text = buff.readLine();

Należy zauważyć, że w kilku pierwszych wierszach kodu po prostu tworzymy łańcuch -obiektów Stream, ale rzeczywiste dane nie są jeszcze przekazywane w dół tego łańcucha strumienia.

I tylko wtedy, gdy wywołamy metodę, buff.readLine()nastąpi:

  1. Obiekt BufferedReaderwywoła metodę read()na obiekcieInputStreamReader
  2. Obiekt InputStreamReaderwywoła metodę read()na obiekcieFileInputStream
  3. Obiekt FileInputStreamzacznie odczytywać dane z pliku

Te. nie ma ruchu danych wzdłuż łańcucha strumieni, dopóki nie zaczniemy wywoływać metod typu read()lub readLine(). Sama konstrukcja łańcucha przepływów nie napędza przez nie danych. Same strumienie nie przechowują danych, a jedynie odczytują od innych.

Kolekcje i strumienie

Począwszy od Javy 8 stało się możliwe uzyskanie strumienia do odczytu danych ze zbiorów (i nie tylko z nich). Ale nie to jest najciekawsze. W rzeczywistości stało się możliwe łatwe i proste konstruowanie złożonych łańcuchów przepływów danych, podczas gdy kod, który wcześniej wymagał 5-10 linii, teraz można było napisać w 1-2 liniach.

Przykład - znajdź łańcuch o maksymalnej długości na liście ciągów:

Znalezienie łańcucha o maksymalnej długości
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Cześć", "Jak", "дела?");
String max = list.stream().max((s1, s2)-> s1.length()-s2.length()).get();
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Cześć", "Jak", "дела?");
Stream<String> stream = list.stream();
Optional<String> optional = stream.max((s1, s2)-> s1.length()-s2.length());
String max = optional.get();

3. InterfejsStream

Rozszerzona obsługa wątków w Javie 8 jest realizowana przy użyciu Stream<T>. Gdzie Tjest parametrem typu, który wskazuje typ danych przekazywanych w strumieniu. Innymi słowy, strumień jest całkowicie niezależny od typu danych, które przekazuje.

Aby pobrać obiekt strumienia z kolekcji , po prostu wywołaj jego stream(). Ten kod wygląda następująco:

Stream<Тип> Nazwa = коллекция.stream();
Pobieranie strumienia z kolekcji

W takim przypadku zbiór będzie traktowany jako źródło danych strumienia, a obiekt typu Stream<Тип>jako narzędzie do pozyskiwania danych ze zbioru w postaci strumienia danych.

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Cześć", "Jak", "дела?");
Stream<String> stream = list.stream();

Nawiasem mówiąc, możesz uzyskać strumień nie tylko z kolekcji, ale także z tablicy . Aby to zrobić, użyj metody Example:Arrays.stream();

Stream<Тип> Nazwa = Arrays.stream(массив);
Pobieranie strumienia z tablicy

W takim przypadku tablica zostanie uznana za źródło danych dla strumienia Nazwa .

Integer[] array = {1, 2, 3};
Stream<Integer> stream = Arrays.stream(array);

Po utworzeniu obiektu Stream<Тип>nie następuje żadne przenoszenie danych. Właśnie otrzymaliśmy obiekt strumienia, aby rozpocząć budowanie łańcucha strumieni danych.