1. Иновации в Java 8: Функционално програмиране

С пускането на Java 8 езикът получи мощна поддръжка за функционално програмиране . Може дори да се каже, че получи дългоочакваната поддръжка за функционално програмиране. Кодирането стана по-бързо, въпреки че codeът беше по-труден за четене 🙂

Преди да научите функционално програмиране в Java, ви препоръчваме да разберете добре три неща:

  1. OOP, наследяване и интерфейси ( Нива 1-2 в търсенето на Java Core ).
  2. Реализации на метод по подразбиране в интерфейс .
  3. Вътрешни и анонимни класове .

Добрата новина е, че не е нужно да знаете всичко това, за да използвате много от функциите на функционалното програмиране в Java. Лошата новина е, че ще бъде трудно да разберете How точно е подредено всичко и How работи всичко, без да знаете за анонимни вътрешни класове.

В предстоящите уроци ще се съсредоточим върху това колко лесно и просто е да използвате функциите за функционално програмиране на Java, без да разбирате задълбочено How работи.

Необходими са месеци, за да разберете всички нюанси на функционалното програмиране в Java. Можете да се научите да четете такъв code за няколко часа. Затова ви предлагаме да започнете с малко. Дори да е с I/O потоци.


2. I/O потоци: тръбопроводи за потоци

Спомняте ли си, че някога сте научor за I/O потоци: InputStream, OutputStream, Readerи Writerт.н.?

Имаше класове на потоци, които четат данни от източници на данни , като например FileInputSteam, и имаше междинни потоци от данни, които четат данни от други потоци, като InputStreamReaderи BufferedReader.

Тези потоци могат да бъдат организирани в тръбопроводи за обработка на данни. Например така:

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

String text = buff.readLine();

Важно е да се отбележи, че в първите няколко реда code ние просто конструираме верига от Streamобекти. Данните все още не са преминали през тръбопровода.

Но веднага щом извикаме buff.readLine()метода, ще се случи следното:

  1. Обектът BufferedReaderизвиква read()метода на InputStreamReaderобекта
  2. Обектът InputStreamReaderизвиква read()метода на FileInputStreamобекта
  3. Обектът FileInputStreamзапочва да чете данни от file

С други думи, няма движение на данни по конвейера на потока, докато не започнем да извикваме методи като read()or readLine(). Самото изграждане на тръбопровода на потока не прекарва данни през него. Самите потоци не съхраняват данни. Четат само от другите.

Колекции и потоци

Започвайки с Java 8, стана възможно да се получи поток за четене на данни от колекции (и не само от тях). Но не това е най-интересното. Всъщност стана възможно лесно и просто да се конструират сложни вериги от потоци от данни. И по този начин codeът, който преди отнемаше 5-10 реда, сега можеше да бъде написан на 1-2 реда.

Пример за намиране на най-дългия низ в списък от низове:

Намиране на най-дългия низ
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
String max = list.stream().max((s1, s2)-> s1.length()-s2.length()).get();
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
Stream<String> stream = list.stream();
Optional<String> optional = stream.max((s1, s2)-> s1.length()-s2.length());
String max = optional.get();

3. Streamинтерфейс

Разширената поддръжка на Java 8 за потоци се реализира с помощта на Stream<T>интерфейса, където Tе параметър тип, който показва типа данни, които се предават в потока. С други думи, потокът е напълно независим от вида на данните, които преминава.

За да получите обект на поток от колекция , просто извикайте неговия stream()метод. Кодът изглежда приблизително така:

Stream<Type> name = collection.stream();
Получаване на поток от колекция

В този случай колекцията ще се счита за източник на данни на потока, а Stream<Type>обектът ще бъде инструмент за получаване на данни от колекцията под формата на поток от данни.

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Hello", "how's", "life?");
Stream<String> stream = list.stream();

Между другото, можете да получите поток не само от колекции, но и от масиви . За да направите това, трябва да използвате метода. Например:Arrays.stream()

Stream<Type> name = Arrays.stream(array);
Получаване на поток от масив

В този случай масивът ще се счита за източник на данни за потока , наречен name.

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

Stream<Type>При създаването на обекта не се преместват данни . Ние просто получихме обект на поток, за да започнем да изграждаме тръбопровод на поток.