1. Innovationer i Java 8: Funktionell programmering

Med lanseringen av Java 8 fick språket kraftfullt stöd för funktionell programmering . Man kan till och med säga att den fick efterlängtat stöd för funktionell programmering. Kodningen blev snabbare, även om koden var svårare att läsa 🙂

Innan du lär dig funktionell programmering i Java rekommenderar vi att du förstår tre saker väl:

  1. OOP, arv och gränssnitt ( Nivå 1-2 i Java Core-uppdraget) .
  2. Förinställd metodimplementering i ett gränssnitt .
  3. Inre och anonyma klasser .

Den goda nyheten är att du inte behöver veta allt detta för att använda många av funktionerna i funktionell programmering i Java. Den dåliga nyheten är att det blir svårt att förstå exakt hur allt är upplagt och hur allt fungerar utan att veta om anonyma inre klasser.

På de kommande lektionerna kommer vi att fokusera på hur enkelt och enkelt det är att använda Javas funktionella programmeringsfunktioner, utan en djup förståelse för hur det fungerar.

Det tar månader att förstå alla nyanser av funktionell programmering i Java. Du kan lära dig att läsa sådan kod på några timmar. Så vi föreslår att börja i det små. Även om det är med I/O-strömmar.


2. I/O-strömmar: strömledningar

Kommer du ihåg att du en gång i tiden lärde dig om I/O-strömmar: InputStream, OutputStream, Reader, Writeretc.?

Det fanns strömklasser som läste data från datakällor , såsom FileInputSteam, och det fanns mellanliggande dataströmmar som läste data från andra strömmar, såsom InputStreamReaderoch BufferedReader.

Dessa strömmar kan organiseras i pipelines för databehandling. Till exempel, så här:

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

String text = buff.readLine();

Det är viktigt att notera att i de första raderna med kod konstruerar vi bara en kedja av Streamobjekt. Uppgifterna har inte passerat genom pipelinen än.

Men så fort vi anropar buff.readLine()metoden kommer följande att hända:

  1. Objektet BufferedReaderanropar read()metoden på InputStreamReaderobjektet
  2. Objektet InputStreamReaderanropar read()metoden på FileInputStreamobjektet
  3. Objektet FileInputStreambörjar läsa data från filen

Med andra ord, det finns ingen rörelse av data längs strömledningen förrän vi börjar anropa metoder som read()eller readLine(). Blotta konstruktionen av strömledningen driver inte data genom den. Strömmarna själva lagrar inte data. De läser bara från andra.

Samlingar och strömmar

Från och med Java 8 blev det möjligt att få en stream att läsa data från samlingar (och inte bara från dem). Men detta är inte det mest intressanta. Det blev faktiskt möjligt att enkelt och enkelt konstruera komplexa kedjor av dataströmmar. Och på så sätt kunde koden som tidigare tog 5-10 rader nu skrivas i 1-2 rader.

Exempel på att hitta den längsta strängen i en lista med strängar:

Hitta den längsta strängen
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. Streamgränssnitt

Java 8:s utökade stöd för strömmar implementeras med hjälp av Stream<T>gränssnittet, där Tär en typparameter som indikerar vilken typ av data som skickas i strömmen. Med andra ord är en ström helt oberoende av vilken typ av data den skickar.

För att hämta ett strömobjekt från en samling , anrop bara dess stream()metod. Koden ser ungefär ut så här:

Stream<Type> name = collection.stream();
Få en stream från en samling

I det här fallet kommer samlingen att betraktas som strömmens datakälla, och objektet Stream<Type>kommer att vara ett verktyg för att hämta data från samlingen i form av en dataström.

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

Förresten, du kan få en ström inte bara från samlingar utan också från arrayer . För att göra detta måste du använda metoden. Till exempel:Arrays.stream()

Stream<Type> name = Arrays.stream(array);
Få en ström från en array

I det här fallet kommer arrayen att betraktas som datakällan för strömmen som kallas name.

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

Ingen data flyttas när Stream<Type>objektet skapas. Vi skaffade helt enkelt ett strömobjekt för att börja bygga en strömledning.