~ Ich habe jetzt versucht, funktionale Programmierung mit Java zu lernen ~

Seit der Veröffentlichung ist ein Jahr vergangen, daher habe ich das Wesentliche des Inhalts nicht geändert und es überprüft und aktualisiert, wobei ich mich darauf konzentriert habe, Erklärungen zur Präsentationsquelle hinzuzufügen.

Einführung

Es ist mehr als 4 Jahre her, seit Java 8 im März 2014 veröffentlicht wurde, und es wurde von vielen Menschen verwendet, einschließlich Java 9 und Java 10 und höher. Funktionale Programmierung wurde zu einem heißen Thema, als Java 8 veröffentlicht wurde. Heutzutage ist der Begriff funktionale Programmierung bei Systementwicklern allgemein anerkannt und weit verbreitet. Es scheint jedoch, dass die tatsächliche Durchdringung noch weit entfernt ist, da die aktuelle Situation darin besteht, dass wir die Systementwicklungsergebnisse der funktionalen Programmierung nicht häufig sehen. Und wie in Java 8 werden auch vorhandene Sprachen durch die Integration eines funktionalen Programmierstils erweitert. Ich kann nicht vorhersagen, wie der Ablauf in Zukunft aussehen wird, aber ich persönlich spekuliere, dass die Verwendung des funktionalen Programmierstils in vorhandenen Sprachen zum Mainstream wird. Ich denke, dass eine reine funktionale Sprache eine spezielle Verwendung sein wird, und im Java-System wird Scala die Java-Sprache nicht ersetzen. Die funktionale Programmierung scheint sich in einer solchen Situation zu befinden, aber es wird erwartet, dass sie sich in Zukunft auf irgendeine Weise ausbreiten wird. Deshalb habe ich eine allgemeine Umfrage durchgeführt und versucht, die einfache Programmierung in der Java 10-Umgebung zu üben. .. Außerdem habe ich beschlossen, die Lernergebnisse als Memorandum zu veröffentlichen, da ich dachte, dass dies für Interessierte hilfreich sein könnte. Bitte beachten Sie, dass der Inhalt einen subjektiven Teil oder einen Programmstil haben kann, der persönliche Orientierung beinhaltet. Informationen zu Wörtern und Phrasen, die für die Funktionsprogrammierung spezifisch sind, finden Sie in den kurzen Erläuterungen innerhalb des am Ende verstandenen Bereichs. (* Wörter mit Zahlen)

Java 8 neue Funktionen hinzugefügt

Java 8 fügt die folgenden neuen Funktionen für die Funktionsprogrammierung hinzu:

Bevor ich auf diese Einführungen eingehe, möchte ich kurz erklären, was funktionale Programmierung überhaupt ist.

Was ist funktionale Programmierung?

Im engeren Sinne ist funktionale Programmierung "eine Methode zum Erstellen eines Programms mit Funktionen, die Referenztransparenz (* 9) und keine Nebenwirkungen (* 8) aufweisen", und diese Definition basiert auf einer funktionalen Sprache. Es ist jetzt jedoch möglich, es auch in vorhandenen Sprachen im funktionalen Programmierstil zu implementieren. Hier haben wir uns entschlossen, einen umfassenden Überblick über die funktionale Programmierung zu erhalten, und drei Funktionen aufgelistet.

  1. Vereinfachen Sie die Programmierung, indem Sie die Möglichkeit nutzen, eine Funktion (z. B. einen Lambda-Ausdruck) als Funktionsargument zu übergeben.
  2. Vereinfachen Sie die Programmierung und verbessern Sie die Qualität, indem Sie verschiedene Methoden (Funktionen) und Grammatiken für die funktionale Programmierung verwenden, die von Sprachen und APIs bereitgestellt werden.

Ich denke, dass das Erstellen eines Programms mit der oben genannten Methode und dem oben genannten Zweck aus einer breiten Perspektive als funktionale Programmierung erkannt werden kann. Darüber hinaus ist die funktionale Programmierung nicht an Entwicklungsmethoden wie den Entwurfsprozess der Anforderungsanalyse wie objektorientiert gebunden, sondern für den Programmimplementierungsprozess selbst vorgesehen. Um funktionale Programmierung durchzuführen, gibt es solche, die auf Sprachebene unterstützen, wie Haskell und Scala, und solche, die einer vorhandenen Sprache wie Java 8 eine API für funktionale Programmierung hinzufügen. Es wird gesagt, dass Java 8 den Bereich von 1 bis 2 abdecken kann und Haskell und Scala den Bereich von 1 bis 3 abdecken können. Eine Programmiersprache, die Nebenwirkungen fast vermeiden kann, wird auch als rein funktionale Programmiersprache bezeichnet, und unter diesem Gesichtspunkt wird Scalas 3. eher als Quasi-Drei als als reine 3 betrachtet. Es versteht sich jedoch von selbst, dass es vom Projekt abhängt, ob das System mit "Funktionen konfiguriert werden muss, die Nebenwirkungen fast vermeiden". Bei der funktionalen Programmierung wird eine relativ kleine Funktion erstellt und angewendet oder kombiniert, um ein System zu entwickeln, das auf dem Format der deklarativen Programmierung (* 3) basiert. Um Level 3 zu implementieren, ist es daher erforderlich, das Konzept der funktionalen Sprache und der funktionalen Programmierung vollständig zu verstehen und nicht das herkömmliche objektorientierte Programmierverfahren. Darüber hinaus muss im Voraus vollständig verstanden werden, wie gut das Zielproblem mit der funktionalen Programmierung übereinstimmt, z. B. dem verknüpften System, der Plattform-Middleware, dem Plattform-Framework, den zugehörigen akkumulierten Assets und der Entwicklungs- / Management- / Betriebsumgebung. es gibt....

Es scheint von Fall zu Fall einige Situationen für das 4. und 5. Element zu geben, aber es scheint sicher, dass der Programmieraufwand für die zutreffenden Teile reduziert wird. Andererseits besteht der Nachteil darin, dass es theoretisch möglich ist, mit reiner Funktionsprogrammierung zu entwickeln, wenn das Entwicklungssystem mathematisch ausgedrückt werden kann. In Wirklichkeit gibt es jedoch nur wenige solcher Umgebungen, insbesondere die CRUD-Verarbeitung in Geschäftssystemen. Es wird gesagt, dass die Hauptanwendung nicht viel Verdienst hat. Java8 führt neue Mechanismen wie Funktionsschnittstellen, Lambda-Ausdrücke, Streams und Optional ein, um die Funktionsprogrammierung zu unterstützen. Dies ermöglicht es, einige der traditionellen Lehrprogrammierungen in einem funktionalen Programmierstil (deklarative Programmierung) zu schreiben. Und wenn Sie mit diesem Java 8 oder höher funktionale Programmierung durchführen,

  1. Verwenden Sie so weit wie möglich neue APIs, die auf objektorientierter Programmierung basieren. (Hauptsächlich reduzierte Codierungsmenge)
  2. Gehen Sie etwas weiter und implementieren Sie die Methode, indem Sie eine Funktion mit Referenztransparenz (vorzugsweise ohne Nebenwirkungen) so weit wie möglich erstellen und verwenden. (Reduzierte Codierungsmenge und verbesserte Qualität)

Ich denke, es gibt zwei Fälle, aber ich persönlich denke, es ist besser, die Schritte (1) → (2) zu unternehmen, um zu lernen. Beachten Sie, dass die funktionale Programmierung nur unter Java 8 und höher funktioniert. Um mit älteren Java-Versionen wie Java6 und Java7 arbeiten zu können, ist es notwendig, mit der Lehrprogrammierung wie zuvor zu entwickeln, nicht mit der funktionalen Programmierung.

Übersicht über die neuen Java 8-Funktionen

Die wichtigsten neuen und aktualisierten Methoden zur funktionalen Programmierung in Java 8 lauten wie folgt. Diese Methoden werden verwendet, um die Grundfunktionalität der funktionalen Programmierung zu nutzen. Ich denke, es kann so ausgedrückt werden, dass funktionale Programmierung in eine objektorientierte Sprache integriert wird. Sie können die Details jeder dieser Methoden leicht online oder in Büchern herausfinden. Hier geben wir einen Überblick über jede Methode und eine Auswahl typischer Methoden.

・ Funktionsschnittstelle Lambda-Ausdrücke und Methodenreferenzen (* 7) können über die Funktionsschnittstelle verwendet werden. Sie können Ihre eigenen erstellen, es stehen jedoch mehrere Standardfunktionsschnittstellen zur Verfügung.

(): Name der Hauptmethode, Argumenttyp → Rückgabetyp Das Folgende ist ein einfaches Definitions- und Verwendungsbeispiel einer selbst erstellten Funktionstypschnittstelle.

[Schnittstellenbeispiel Verwandte Codebeschreibung]

InterfaceExample


001 public class InterfaceExample{
002     public static void main(String[] args){
003     IHobby hb = (String hobby) -> {
004       return "my hobby : " + hobby;
005     };
006     System.out.println(hb.getHobby("cycling"));
007   }
008 }

009 @FunctionalInterface
010 interface IHobby{
011   public String getHobby(String hobby);
012 }

Unten finden Sie ein einfaches Beispiel für die Verwendung der Funktionsstandard-Funktionsschnittstelle.

[LambdaParameter-bezogene Codebeschreibung]

LambdaParameter


001 package functiontest;

002 import java.io.IOException;
003 import java.util.function.Function;

004 public final class LambdaParameter {

005   public static void main(String[] args) throws IOException {
006     Integer value = 1;
007     Integer res = execute(value, t -> {
008       return getFiveTimes(t);
009     });
010     System.out.println("Ergebnis:" + res);
011   }

      /**
      *Argument Funktionsschnittstelle(Lambda-Stil)Ausführungsmethode
      */
012   public static <R> R execute(Integer value, Function<Integer, R> fnc) {
013     R rtnval = fnc.apply(value);
014     return rtnval;
015   }

      /**
      *Methode zur Ausführung der Betonbearbeitung(Multiplizieren Sie den Wert mit 5)
      */
016   public static Integer getFiveTimes(Integer value) {
017     return value * 5;
018   }

019 }

· Karte Der vorhandenen Map-Klasse wurden auch neue Methoden hinzugefügt. Die wichtigsten hinzugefügten Methoden sind forEach, replaceAll, computeIfAbsent, computeIfPresent, compute und merge.

Unten finden Sie ein einfaches Beispiel. (k: Kartenschlüssel v: Kartenwert p: Argumentwertschlüssel: Angegebener Schlüssel)

[Kartenbezogene Codebeschreibung] Der Map-Typ ist String, String. ・ ForEach (001): Gibt alle Elemente der Karte im Format [Schlüssel: Wert] aus. ・ ReplaceAll (002 ~): Ersetzen Sie die Werte aller Kartenelemente durch null → [Schlüssel] und ungleich Null → [Schlüssel + erste 2 Wertzeichen]. ・ ComputeIfAbsent (008 ~): a. Wenn der Schlüssel im Kartenschlüssel vorhanden ist Der Wert wird nicht aktualisiert und der Wert ist der Rückgabewert. b. Wenn der Schlüssel vorhanden ist und der Wert null ist Der Wert wird auf [Schlüssel + "-Addition"] aktualisiert und dieser Wert ist der Rückgabewert. c. Wenn es im Schlüssel nicht vorhanden ist Fügen Sie einen Wert mit Schlüssel und Wert [Schlüssel + "-Addition"] zur Zuordnung hinzu, und dieser Wert ist der Rückgabewert. ・ ComputeIfPresent (011 ~): a. Wenn der Schlüssel im Kartenschlüssel vorhanden ist Der Wert wird auf [Schlüssel + Wert + "-Addition"] aktualisiert und dieser Wert ist der Rückgabewert. b. Wenn der Schlüssel vorhanden ist und der Wert null ist Der Wert wird nicht aktualisiert und null ist der Rückgabewert. c. Wenn es im Schlüssel nicht vorhanden ist Der Wert wird nicht hinzugefügt oder aktualisiert, und null ist der Rückgabewert. ・ Berechnen (014 ~): a. Wenn der Schlüssel im Kartenschlüssel vorhanden ist Der Wert wird auf [Schlüssel + Wert + "-Addition"] aktualisiert und dieser Wert ist der Rückgabewert. b. Wenn der Schlüssel vorhanden ist und der Wert null ist Der Wert wird auf [Schlüssel + Wert (null) + "-Addition"] aktualisiert, und dieser Wert ist der Rückgabewert. c. Wenn es im Schlüssel nicht vorhanden ist Fügen Sie das Element (Schlüssel, [Schlüssel + Wert (null) + "-Addition"]) zur Karte hinzu, und dieser Wert ist der Rückgabewert. ・ Zusammenführen (017 ~): a. Wenn der Schlüssel im Kartenschlüssel vorhanden ist Der Wert wird auf [Wert + "-add"] aktualisiert und dieser Wert ist der Rückgabewert. b. Wenn der Schlüssel vorhanden ist und der Wert null ist Der Wert wird auf ["-add"] aktualisiert (wobei Nullwerte ignoriert werden) und dieser Wert ist der Rückgabewert. c. Wenn es im Schlüssel nicht vorhanden ist Fügen Sie das Element (Schlüssel, ["-add"]) (ignorieren Sie den Nullwert) zur Karte hinzu, und dieser Wert ist der Rückgabewert.

MapMethod


    forEach:
001   map.forEach((k, v) -> System.out.println(k + ":" + v));
    replaceAll:
002   map.replaceAll((k, v) -> {
003     if (null == v) {
004       return k;
005     }
006     return k + v.substring(0, 2);
007   });
    computeIfAbsent:
008   map.computeIfAbsent(key, k -> {
009     return k + "-addition";
010   });
    computeIfPresent:
011   map.computeIfPresent(key, (k, v) -> {
012     return k + v + "-addition";
013   });
    compute:
014   map.compute(key, (k, v) -> {
015     return k + v + "-addition";
016   });
    merge:
017   map.merge(key, "-add", (v, p) -> v + p);

· Aufführen Der vorhandenen List-Klasse wurden auch neue Methoden hinzugefügt. Die wichtigsten hinzugefügten Methoden sind forEach, removeIf, replaceAll, stream und parallelStream.

Unten finden Sie ein einfaches Beispiel. (v: Listenwert Wert: externer Wert)

[Liste der zugehörigen Codebeschreibungen] Der Listentyp ist String. ・ ForEach (001): Gibt Werte für alle Elemente der Liste aus. ・ RemoveIf (002 ~): Die Liste enthält einen bestimmten Wert: Das entsprechende Element wird gelöscht und true zurückgegeben. b. Der angegebene Wert ist null: Das entsprechende Element wird nicht gelöscht und false wird zurückgegeben. c. Kein angegebener Wert: Das Element wird nicht gelöscht und false wird zurückgegeben. ・ ReplaceAll (008 ~): Nicht-Null-Wert für alle Elemente: Auf die ersten 2 Zeichen des Werts aktualisiert. b. Nullwert für alle Elemente: Der Wert wird nicht aktualisiert. ・ Sortieren (014): a. Die Sortierung nach natürlicher Reihenfolge / Null-Maximalwert wird für alle Elemente durchgeführt. ・ Stream (015): a. Holen Sie sich den Stream der Liste. ・ ParallelStream (016): a. Holen Sie sich einen parallelen Listenstrom.

ListMethod


    forEach:
001   list.forEach(v -> System.out.println(v));
    removeIf:
002   list.removeIf(v -> {
003     if (null == v) {
004       return false;
005     }
006     return v.equals(value);
007   });
    replaceAll:
008   list.replaceAll(v -> {
009     if (null == v) {
010       return v;
011     }
012     return v.substring(0, 2);
013   });
    sort:
014   list.sort(Comparator.nullsLast(Comparator.naturalOrder()));
    stream:
015   Stream sm = list.stream();
    parallelStream:
016   Stream sm = list.parallelStream();

・ Stream-API Es ist eine API für die Verarbeitung von Arrays und Sammlungen und kann für die Datenverarbeitung wie die Aggregation von Werten verwendet werden. Stream-Methoden werden je nach Operationsinhalt in zwei Typen eingeteilt, einen für die Zwischenverarbeitung und einen für die Beendigungsverarbeitung. Führen Sie die Beendigungsverarbeitungsmethode über 0 oder mehr Zwischenverarbeitungsmethoden aus. Eine primitive Stream-API ist ebenfalls verfügbar. Methode zur Zwischenverarbeitung asDoubleStream、asLongStream、boxed、distinct、filter、flatMap、flatMapToDouble、flatMapToInt、flatMapToLong、limit、map、mapToDouble、mapToInt、mapToLong、mapToObj、onClose、parallel、peek、sequential、skip、sorted、unordered Das Folgende ist eine kurze Beschreibung typischer Methoden.

Unten finden Sie ein einfaches Beispiel. (Stream: Stream-Instanz v: Stream-Werteliste: Externe Liste numlimit: Externer Wert)

[Beschreibung des Stream-bezogenen Codes (Zwischenverarbeitung)] Der Stream-Typ ist Integer. ・ Filter (001 ~): a. Stream Extrahiert ein Vielfaches von 3 für alle Elemente und kehrt mit Stream zurück. ・ Karte (004): Der Name der Zeichenfolgendatei wird in einer Liste gespeichert, die von Liste zu Stream konvertiert wird. b. Danach wird nach der Konvertierung in Stream dieser Wert zurückgegeben. ・ FlatMap (005 ~): Inhalt verarbeiten: Für jedes Listenelement wird eine Kopie mit "abc" am Anfang erstellt und zurückgegeben. Ein Zeichen halber Breite + eine Ziffer der Zahl wird in der Liste gespeichert, und ein Array von ["abc" + Wert] wird für die Anzahl der Zahlen erstellt. b. Konvertieren Sie dann dieses Array in den Stream-Typ. Außerdem wird dieser Wert in List konvertiert. ・ Unterscheidbar (010): a. Stream Alle Elemente werden mit demselben Typ zurückgegeben, wodurch doppelte Elemente eliminiert werden. ・ Sortiert (011): Die Gesamtzahl der Elemente im Stream wird in aufsteigender Reihenfolge sortiert und im gleichen Typ zurückgegeben. ・ Limit (012): Die Gesamtzahl der Elemente im Stream ist auf numlimit begrenzt und wird mit demselben Typ zurückgegeben.

StreamMethod1


    filter:
001   stream.filter(v -> {
002     return (v%3) == 0;
003   });
    map:
004   list.stream().map(Paths::get);
    flatMap:
005   list.stream().flatMap(v -> {
006     String[] array = new String[Integer.parseInt(v.substring(1))];
007     Arrays.fill(array, "abc" + v);
008     return Stream.of(array);
009   }).collect(Collectors.toList());
    distinct:
010   stream.distinct();
    sorted:
011   stream.sorted();
    limit:
012   stream.limit(numlimit);

Kündigungsmethode allMatch、anyMatch、average、collect、count、findAny、findFirst、forEach、forEachOrdered、iterator、max、min、noneMatch、reduce、spliterator、sum、summaryStatistics、toArray Nachfolgend finden Sie eine kurze Beschreibung typischer Methoden.

Unten finden Sie ein einfaches Beispiel. (Stream: Stream-Instanz v: Stream-Wert-Array: Externes Array AC: Akkumulator)

[Beschreibung des Stream-bezogenen Codes (Terminierungsverarbeitung)] ・ AllMatch (001 ~): Der Stream wird unter der Bedingung "Alle Übereinstimmungen" (0 10) überprüft. Gibt true zurück, wenn alle Elemente übereinstimmen. ・ AnyMatch (007 ~): a. Der Stream wird mit einer beliebigen Bedingung (= 5) überprüft. : Wenn eine oder mehrere Übereinstimmungen vorliegen, wird true zurückgegeben. ・ Sammeln (010 ~): Beispiel 1: Konvertieren eines Arrays in einen Stream und Verwenden der toList-Methode der Collectors-Klasse, um den Listentyp zurückzugeben. Die Collectors-Klasse verfügt über mehrere Methoden zum Konvertieren von Streams in andere Klassen. b. Beispiel 2: Konvertieren einer Liste in einen Stream, Speichern des Stream-Werts in einem StringBuilder und Zurückgeben des gleichen Typs. (Die tatsächliche Bedeutung des dritten Arguments ist in diesem Fall nicht. Bei der Parallelverarbeitung hat es normalerweise eine Bedeutung.) Die Argumentbeschreibung der Collect-Methode lautet wie folgt.

StreamMethod2


    allMatch:
001   stream.allMatch(v -> {
002     if ((0 < v) && (10 > v)) {
003       return true;
004     }
005     return false;
006   });
    anyMatch:
007   stream.anyMatch(v -> {
008     return v.equals(5);
009   });
    collect:(Es gibt mehrere Typen)
010   //Beispiel 1:Arrays.stream(array).collect(Collectors.toList());
011   //Beispiel 2:list.stream().collect(StringBuilder::new, (b, v) -> b.append(v), (b1, b2) -> b1.append(b2));
      //1. Argument:Ergebnisspeicherobjektgenerierung, 2. Argument:Speichern Sie das dritte Argument des Stream-Werts:Objektverknüpfung
    count:
012   list.stream().count();
    reduce:(Es gibt mehrere Typen)
013   list.stream().reduce((ac, v) -> ac + v);
    max:
014   list.stream().max(Comparator.naturalOrder());
    min:
015   list.stream().min(Comparator.naturalOrder());
    toArray:
016   Object[] array = list.stream().toArray();
    filter+forEach:
017   stream.filter(v -> {
018     return v%3 == 0;
019   }).forEach(System.out::println);

· Optional Optional ist eine Klasse, die einen Wert umschließt. Sie können nach Nullen und Werten suchen. Optional.ofNullable, Optional.empty (), opt.isPresent (), ...

Beispiel für funktionale Programmierung in Java 8

Es gibt viele Beispiele für mehrere Zeilen im Netz und in Büchern, aber hier werde ich ein Beispiel für ein Level mit einer bestimmten Funktion vorstellen. Funktionsprogrammierung sollte jedoch nicht so durchgeführt werden, sondern wird aus der Perspektive der Referenzcodierung für ein rudimentäres Verständnis erstellt. Funktionen sind Produktinventarverwaltung und bestehen aus zwei Klassen, der Hauptklasse und der FunctionStock-Klasse. Beachten Sie, dass die FunctionStock-Klasse formal so viele API-Verwendungsbeispiele wie möglich enthält, sodass die funktionale Programmierung auch dann durchgeführt wird, wenn sie nicht benötigt wird. Klassenübersicht StockMain: Die Hauptklasse der Bestandsverwaltung. Wir machen keine funktionale Programmierung. FunctionStock: Eine Klasse, die tatsächlich Inventar verarbeitet. Ich mache funktionale Programmierung mit mehreren Methoden. IStock: Schnittstelle der Inventarverarbeitungsklasse. IStockExecuter: Homebrew-Funktionsschnittstelle für die Bestandsverarbeitung. Die detaillierte Funktion und den Kommentar der Methodenübersicht finden Sie im Kommentar der Hauptklasse. Die Art der von der Markierung ☆ verwendeten Funktionsprogrammierung wird beschrieben.

[StockMain-bezogene Codebeschreibung] Karten, in denen die Anzahl der Bestände und Zubehörkonfigurationen gespeichert sind, sind in den Jahren 013 bis 014 definiert. Von 025 bis 036 werden 6 Artikel und die anfängliche Lagermenge eingestellt. CD und Magazin haben Zubehör. Die spezifische Verarbeitung wird in 016 bis 022 eingestellt. Das Buch definiert zwei Kaufprozesse und einen Verkaufsprozess. Magazin definiert einen Verkaufsprozess. Schließlich wird der Ausgabeprozess der Inventarliste definiert. 037 bis 046 führen den Kaufvorgang mit der Lagermethode aus. 047 bis 056 führen die Verkaufsabwicklung mit der Verkaufsmethode aus. Die Menge ist negativ. 057 bis 066 geben die Lagermenge des angegebenen Produkts nach der Methode get aus. 067 bis 076 geben die Inventarliste der Produkte mit der Methode getList aus. Die Einkaufsabwicklung, die Verkaufsabwicklung, die Ausgabe der Bestandsmenge und die Ausgabe der Bestandsliste werden alle von der Ausführungsmethode von FunctionStock ausgeführt.

StockMain.java


001 package stocksample;

002 import java.util.Arrays;
003 import java.util.List;
004 import java.util.Map;
005 import java.util.TreeMap;

    /**
     *Hauptklasse der Bestandsführung
     *Funktion: Einkaufsprozess(stock), Verkaufsabwicklung(sale), Inventarprüfungsverarbeitung(get), Verarbeitung der Inventarlistenausgabe(getList)
     * (): Methodenname
     *Bestandsdatenverarbeitungsformat: Methodenname(Produktname,Menge)
     *Zubehör für jedes Produkt(Mehrfach möglich, aber jede Menge ist auf eins begrenzt)Wird beigefügt und das Inventar des Zubehörs wird ebenfalls verwaltet.
     *Kaufprozess: Erhöhen Sie die Anzahl der angegebenen Produkte auf Lager um die Anzahl der Käufe. Wenn das angegebene Produkt nicht registriert ist, wird auch das Produkt registriert.
     *Verkaufsabwicklung: Reduzieren Sie die Anzahl der angegebenen Produkte auf Lager um die Anzahl der verkauften Produkte. Wenn jedoch kein Lagerbestand einschließlich Zubehör vorhanden ist, wird die Verarbeitung gestoppt.
     *Bestandsprüfungsverarbeitung: Gibt die Anzahl der angegebenen Produkte auf Lager aus.
     *Bestandslisten-Ausgabeverarbeitung: Gibt die Anzahl der Bestände aller Produkte aus. Die Zubehörliste wird ebenfalls ausgegeben.
     *Behandlung von Fehlern: Gibt eine Fehlermeldung aus, wenn sie auftritt, und bricht die nachfolgende Verarbeitung ab.
     */
006 public class StockMain {
007   private static Map<String, Integer> stockMap;
008   private static Map<String, List<String>> subStockMap;
009   private static IStock stockObject;
010   private static final boolean funcOption = true; //JDK8-Version
      //private static final boolean funcOption = false; //JDK6,JDK7-Version

011   public static void main(String[] args) {
012     System.out.println("**start**");
        //
        //Stellen Sie den anfänglichen Kartenwert ein
013     stockMap = new TreeMap<String, Integer>();
014     subStockMap = new TreeMap<String, List<String>>();
015     setInitialMap();
        //
        //Bestandsdatenverarbeitung
016     stock("book", 1);
017     stock("book", 2);
018     sale("book", 2);
019     get("book");
020     sale("magazine", 2);
021     get("magazine");
022     getList();
        //
023     System.out.println("**end**");
024   }

      /**
      *Methode zum Festlegen des anfänglichen Kartenwerts
      */
025   private static void setInitialMap() {
026     List<String> cdlist = Arrays.asList("posterA", "posterB", "posterC");
027     subStockMap.put("cd", cdlist);
028     List<String> mglist = Arrays.asList("bagA");
029     subStockMap.put("magazine", mglist);
030     stockMap.put("cd", 3);
031     stockMap.put("magazine", 3);
032     stockMap.put("posterA", 3);
033     stockMap.put("posterB", 3);
034     stockMap.put("posterC", 3);
035     stockMap.put("bagA", 3);
036   }

      /**
      *Methode zur Durchführung des Kaufprozesses
      */
037   private static void stock(String productName, int quantity) {
038     if (funcOption) {
039       stockObject = new FunctionStock(productName, quantity, "add");
040     } else {
041       stockObject = new Stock(productName, quantity, "add");
042     }
043     setMap();
044     int result = stockObject.execute();
045     if (0 > result) System.exit(result);
046   }

      /**
      *Methode zur Abwicklung von Verkäufen
      */
047   private static void sale(String productName, int quantity) {
048     if (funcOption) {
049       stockObject = new FunctionStock(productName, -quantity, "add");
050     } else {
051       stockObject = new Stock(productName, -quantity, "add");
052     }
053     setMap();
054     int result = stockObject.execute();
055     if (0 > result) System.exit(result);
056   }

      /**
      *Methode zur Ausgabe der Lagermenge des angegebenen Produkts
      */
057   private static void get(String productName) {
058     if (funcOption) {
059       stockObject = new FunctionStock(productName, "get");
060     } else {
061       stockObject = new Stock(productName, "get");
062     }
063     setMap();
064     int result = stockObject.execute();
065     if (0 > result) System.exit(result);
066   }

      /**
      *Methode zur Ausgabe der Inventarliste
      */
067   private static void getList() {
068     if (funcOption) {
069       stockObject = new FunctionStock("getlist");
070     } else {
071       stockObject = new Stock("getlist");
072     }
073     setMap();
074     int result = stockObject.execute();
075     if (0 > result) System.exit(result);
076   }

      /**
      *Methode zum Festlegen der Zuordnung zum Lagerobjekt
      */
077   private static void setMap() {
078     stockObject.setStockMap(stockMap);
079     stockObject.setSubStockMap(subStockMap);
080   }
081 }

[Funktionsbestandsbezogene Codebeschreibung] Für 028 bis 042 werden Produktname, Menge und Typ im Konstruktor in 013 bis 014 festgelegt. Typ stellt die Art der Verarbeitung dar, und Hinzufügen, Delname, Get und Getlist können angegeben werden. ・ Methode ausführen Die angegebenen Bestandsdaten werden zur Bestätigung um 044 ausgegeben. Überprüfung der angegebenen Bestandsdaten von 045 bis 048. Überprüfen Sie die Inventardaten mit der Methode getDataCheckFunction (). Get (), rufen Sie die Ergebniszeichenfolge ab, konvertieren Sie sie mit Optional.ofNullable in Optional, führen Sie mit ifPresent eine optionale Nullbeurteilung durch und zeigen Sie bei einem Fehler einen Fehler mit outputErrorMessage an Ich werde. In 052 wird die Bestandsdatenverarbeitung durch die Methode executeStock (). Execute () (selbst erstellte Funktionsschnittstelle IStockExecuter) ausgeführt, und das Verarbeitungsergebnis wird im optionalen generischen Typ Integer gespeichert. Um 053 wird die Fehlermeldung bei der Bestandsdatenverarbeitung von der Methode getErrorKeyFunction () generiert. Die Methode (result) anwenden und von outputErrorMessage ausgeben. -GetDataCheckFunction-Methode 066 bis 078 definiert die Implementierung einer Funktionsschnittstelle (generischer Lieferantentyp: String), die Inventardaten überprüft (Nullprüfung usw.). ・ ExecuteStock-Methode 079 bis 096 definieren eine funktionale Schnittstellenimplementierung (von IStockExecuter), die Inventardaten verarbeitet (Verarbeitungstypen: add, delname, get, getlist). Es ruft updateStock (). Get (), deleteStockName (). Get (), getStock (). Get (), outputStockList (getStockList (). Get ()), outputSubStockList () auf. ・ UpdateStock-Methode 097 bis 126 definieren die Implementierung einer funktionalen Schnittstelle (generischer Lieferantentyp Optional), die die Anzahl der Bestände aktualisiert. Die Bestandsmenge wird mit der Methode addToStockMap (). Apply (・ ・) aktualisiert. ・ AddToStockMap-Methode Definiert die Implementierung einer Funktionstypschnittstelle (generischer BiFunction-Typ: String, Integer, Optional), die speziell die Anzahl der Bestände in 127 bis 138 aktualisiert. Die Berechnungsmethode von Map wird verwendet, um die Anzahl der Bestände zu erhöhen oder zu verringern. -DeleteStockName-Methode 139 bis 147 definieren die Implementierung einer funktionalen Schnittstelle (generischer Lieferantentyp: Optional), die zu lagernde Artikel löscht (Bestandsdaten). Die Entfernungsmethode von Map wird verwendet, um die Artikel auf Lager zu löschen. ・ GetStock-Methode 148 bis 154 definieren die Implementierung einer funktionalen Schnittstelle (generischer Lieferantentyp: Optional), die die Anzahl der Bestände eines bestimmten Artikels erfasst. Die Bestandsmenge wird mit der getOrDefault-Methode von Map erfasst. ・ GetStockList-Methode Definiert die Implementierung einer Funktionsschnittstelle (generischer Lieferantentyp: String), die die Bestandsmengenliste in 155 bis 166 abruft. Die Inventarliste wird mit der forEach-Methode von Map erstellt. -GetErrorKeyFunction-Methode 167 bis 175 definieren die Implementierung einer Funktionstypschnittstelle (generischer Funktionstyp: Optional, Zeichenfolge), die das Ergebnis der Bestandsverarbeitung überprüft. Die optionale Zuordnungsmethode (Errindex) definiert die Nachrichtengenerierung im Fehlerfall. -OutputSubStockList-Methode Eine Liste des Zubehörs wird von 191 bis 204 ausgegeben. Die zusätzlichen Ausgabeinformationen für ein bestimmtes Element werden von der Erfassungsmethode nach dem Konvertieren von Liste zu Stream generiert. -OutputErrorMessage-Methode Für messageKey werden Fehlermeldungen von 205 bis 220 ausgegeben. Nach dem Konvertieren von messageKey in Optional wird von der Map-Methode eine Fehlermeldung generiert.

FunctionStock.java


001 package stocksample;

002 import java.util.Arrays;
003 import java.util.List;
004 import java.util.Map;
005 import java.util.Optional;
006 import java.util.function.BiFunction;
007 import java.util.function.Function;
008 import java.util.function.Supplier;

    /**
     *Bestandsverwaltungsklasse
     */
009 public final class FunctionStock implements IStock {
010   private String productName;
011   private int quantity;
012   private Map<String, Integer> stockMap;
013   private Map<String, List<String>> subStockMap;
014   private String type;
015   private String errorKey;
016   private String errorProductName;
017   private final List<String> typeList = Arrays.asList("add", "delname", "get");
018   private final List<String> errorKeyList = Arrays.asList("zerostock,subzerostock", "noname", "noname");
019   private final List<String> errorMessageKeyList= Arrays.asList(
020   "nullname", "noname", "number", "zerostock", "subzerostock","keyerror");
021   private final List<String> errorMessageList= Arrays.asList(
022   "★ Der Produktname ist nicht angegeben.",
023   "★ Der in der Inventarliste angegebene Produktname existiert nicht.",
024   "★ Die Menge ist nicht angegeben.",
025   "★ Der Lagerbestand wird unter Null liegen.<%p1%> <%p2%>Stücke",
026   "★ Die Menge des auf Lager befindlichen Zubehörs ist kleiner als Null.<%p1%> <%p2%>Stücke",
027   "★ Der Schlüssel ist abnormal.");

      /**
      *Konstrukteur
      */
028   public FunctionStock(String productName, int quantity, String type) {
029     this.productName = productName;
030     this.quantity = quantity;
031     this.type = type;
032   };

      /**
      *Konstrukteur
      */
033   public FunctionStock(String productName, String type) {
034     this.productName = productName;
035     this.quantity = 0;
036     this.type = type;
037   };

      /**
      *Konstrukteur
      */
038   public FunctionStock(String type) {
039     this.productName = "";
040     this.quantity = 0;
041     this.type = type;
042   };

      /**
      *Methode zur Verarbeitung von Inventardaten
      *☆ Verwenden Sie die optionalen Methoden Nullable, ifPresent und orElse
      *☆ Verwenden Sie die Apply-Methode der Funktionsschnittstelle
      */
043   public int execute() {
        //Ausgabe von Inventardaten
044     outputData();
        //Bestandsdatenprüfung
045     Optional.ofNullable(getDataCheckFunction().get()).ifPresent(ekey -> {
046       outputErrorMessage(ekey);
047       errorKey = ekey;
048     });
049     if (null != errorKey) {
050       return -1;
051     }
        //Bestandsdatenverarbeitung
052     Optional<Integer> result = executeStock().execute();
        //Fehlerausgabe
053     outputErrorMessage(getErrorKeyFunction().apply(result));
054     return result.orElse(-1);
055   }

      /**
      *Methode zur Ausgabe von Inventardaten
      */
056   private void outputData() {
057     StringBuilder sb = new StringBuilder();
058     sb.append("Daten verarbeiten:");
059     sb.append(productName);
060     sb.append(",");
061     sb.append(quantity);
062     sb.append(",");
063     sb.append(type);
064     System.out.println(sb.toString());
065   }

      /**
      *Methode zur Überprüfung der Inventardaten
      *☆ Verwendet Funktionsschnittstelle Lieferant
      */
066   private Supplier<String> getDataCheckFunction() {
067     return () -> {
068       if (null == productName || (!"getlist".equals(type) && "".equals(productName))) {
069         return "nullname";
070       }
071       if ("add".equals(type)) {
072         if (0 == quantity) {
073           return "number";
074         }
075       }
076       return null;
077     };
078   }

      /**
      *Methode zur Verarbeitung von Inventardaten
      *☆ Verwenden Sie die selbst erstellte Funktionstyp-Schnittstelle IStockExecuter
      *☆ Verwenden Sie die optionale leere Methode
      */
079   private IStockExecuter executeStock() {
080     return () -> {
081       Optional<Integer> result = Optional.empty();
082       if ("add".equals(type)) {
083         result = updateStock().get();
084       } else if ("delname".equals(type)) {
085         result = deleteStockName().get();
086       } else if ("get".equals(type)) {
087         result = getStock().get();
088       } else if ("getlist".equals(type)) {
089         outputStockList(getStockList().get());
090         outputSubStockList();
091       } else {
092         errorKey = "keyerror";
093       }
094       return result;
095     };
096   }

      /**
      *Methode zum Aktualisieren der Bestandsmenge(Kann erhöht oder verringert werden)
      *☆ Verwendet Funktionsschnittstelle Lieferant
      *☆ Verwenden Sie die Apply-Methode der Funktionsschnittstelle BiFunction
      *☆ Verwenden Sie Optionale Methode
      *☆ Verwenden Sie die List forEach-Methode
      *☆ Verwenden Sie die getOrDefault-Methode von Map
      */
097   private Supplier<Optional<Integer>> updateStock() {
098     return  () -> {
099       if (0 > addToStockMap().apply(productName, quantity).get()) {
100         addToStockMap().apply(productName, -quantity);
101         return Optional.of(-1);
102       }
103       if (0 > quantity) {
104         List<String> slist = subStockMap.get(productName);
105         if (null != slist) {
106           slist.forEach(v  -> {
107             if (null != errorProductName) return;
108             int substock = stockMap.getOrDefault(v, -1);
109             if (-1 == substock || 0 > (substock + quantity)) {
110               errorProductName = v;
111             }
112           });
113           if (null == errorProductName) {
114             slist.forEach(v  -> {
115               addToStockMap().apply(v, quantity);
116             });
117           }
118         }
119         if (null != errorProductName) {
120           addToStockMap().apply(productName, -quantity);
121           return Optional.of(-2);
122         }
123       }
124       return Optional.of(0);
125     };
126   }

      /**
      *Methode zum Aktualisieren des Lagerwerts des Produkts
      *☆ Verwendet die Funktionsschnittstelle BiFunction
      *☆ Verwenden Sie die Berechnungsmethode von Map
      *☆ Verwenden Sie Optionale Methode
      */
127   private BiFunction<String, Integer, Optional<Integer>> addToStockMap() {
128     return (pname, qty) -> {
129       int addedValue = stockMap.compute(pname, (k, v) -> {
130         if (null == v) v = 0;
131         return v + qty;
132       });
133       if (0 > addedValue) {
134         return Optional.of(-1);
135       }
136       return Optional.of(addedValue);
137     };
138   }

      /**
      *Methode zum Löschen von Bestandsdaten von Waren
      *☆ Verwendet Funktionsschnittstelle Lieferant
      *☆ Verwenden Sie Optional von Nullable, isPresent und von Methoden
      */
139   private Supplier<Optional<Integer>> deleteStockName() {
140     return () -> {
141       int result = -1;
142       if (Optional.ofNullable(stockMap.remove(productName)).isPresent()) {
143         result = 0;
144       }
145       return Optional.of(result);
146     };
147   }

      /**
      *Methode, um die Anzahl der Aktien zu erhalten
      *☆ Verwendet Funktionsschnittstelle Lieferant
      *☆ Verwenden Sie die getOrDefault-Methode von Map
      *☆ Verwenden Sie Optionale Methode
      */
148   private Supplier<Optional<Integer>> getStock() {
149     return () -> {
150       int result = stockMap.getOrDefault(productName, -1);
151       outputNumberStock(result);
152       return Optional.of(result);
153     };
154   }

      /**
      *Methode zum Generieren einer Inventarliste
      *☆ Verwendet Funktionsschnittstelle Lieferant
      *☆ Verwenden Sie die Map forEach-Methode
      */
155   private Supplier<String> getStockList() {
156     return () -> {
157       StringBuilder sb = new StringBuilder();
158       stockMap.forEach((k, v) -> {
159         sb.append(k);
160         sb.append(":");
161         sb.append(v);
162         sb.append("\n");
163       });
164       return sb.toString().substring(0, sb.toString().length()-1);
165     };
166   }

      /**
      *Methode zur Überprüfung des Ergebnisses der Bestandsverarbeitung
      *☆ Funktionstyp-Schnittstelle Funktion verwenden
      *☆ Verwenden Sie die optionalen Methoden map und orElse
      */
167   private Function<Optional<Integer>, String> getErrorKeyFunction() {
168     return errindex -> {
169       Optional<String> opkey = errindex.map(eindex -> {
170         if (0 <= eindex) return "";
171         return errorKeyList.get(typeList.indexOf(type)).split(",")[Math.abs(eindex)-1];
172       });
173       return opkey.orElse("");
174     };
175   }

      /**
      *Methode zur Ausgabe der Anzahl der Bestände
      */
176   private void outputNumberStock(int result) {
177     if (-1 < result) {
178       StringBuilder sb = new StringBuilder();
179       sb.append("☆ Lagermenge des angegebenen Lagernamens:");
180       sb.append(productName);
181       sb.append(" ");
182       sb.append(result);
183       sb.append("Stücke");
184       System.out.println(sb.toString());
185     }
186   }

      /**
      *Methode zur Ausgabe der Inventarliste
      */
187   private void outputStockList(String list) {
188     System.out.println("☆ Inventarliste");
189     System.out.println(list);
190   }

      /**
      *Methode zur Ausgabe der Zubehörliste
      *☆ Verwenden Sie die Methoden Map forEach und getOrDefault
      *☆ Verwenden Sie die Stream-Methode von List
      *☆ Verwenden Sie die Erfassungsmethode von Stream
      */
191   private void outputSubStockList() {
192     System.out.println("☆ Zubehörliste");
193     stockMap.forEach((k, v) -> {
194       List<String> list = subStockMap.getOrDefault(k, null);
195       if (null != list) {
196         StringBuilder sb = list.stream().collect(StringBuilder::new, (ssb, adname) -> {
197           ssb.append(adname);
198           ssb.append(", ");
199         }, (ba, bb) -> {ba.append(bb);});
200         String str = k + " : " + sb.toString();
201         System.out.println(str.substring(0, str.length()-2));
202       }
203     });
204   }

      /**
      *Methode zur Ausgabe einer Fehlermeldung
      *☆ Verwenden Sie die Option Optional ofNullable und Map
      */
205   private void outputErrorMessage(String messageKey) {
206     if ("".equals(messageKey)) return;
207     Optional<String> mes = Optional.ofNullable(messageKey).map(m -> {
208       String messtr = errorMessageList.get(errorMessageKeyList.indexOf(m));
209       if (-1 < messtr.indexOf("<%p")) {
210         String pname = productName;
211         if (null != errorProductName) {
212           pname = errorProductName;
213         }
214         messtr = messtr.replace("<%p1%>", pname).replace("<%p2%>", String.valueOf(stockMap.get(pname)));
215       }
216       return messtr;
217     });
218     System.out.println(mes.get());
219     System.out.println("★ Die Verarbeitung wurde abgebrochen.");
220   }

221   public void setStockMap(Map<String, Integer> stockMap) {
222     this.stockMap = stockMap;
223   }

224   public void setSubStockMap(Map<String, List<String>> subStockMap) {
225     this.subStockMap = subStockMap;
226   }
227 }

IStock.java


001 package stocksample;

002 import java.util.List;
003 import java.util.Map;

004 public interface IStock {
005   public int execute();
006   public void setStockMap(Map<String, Integer> stockMap);
007   public void setSubStockMap(Map<String, List<String>> subStockMap);
008 }

IStockExecuter.java


001 package stocksample;

002 import java.util.Optional;

003 @FunctionalInterface
004 public interface IStockExecuter {
005   public abstract Optional<Integer> execute();
006 }

Zusammenfassung der Implementierung der funktionalen Programmierung

Kurze Erläuterung der Begriffe zur Funktionsprogrammierung

Im Folgenden finden Sie eine kurze Erläuterung der Begriffe zur Funktionsprogrammierung, die häufig im Internet vorkommen. Da es schwierig ist, die Monade zu verstehen, habe ich eine zusätzliche Erklärung hinzugefügt.

  1. Funktionsschnittstelle: Eine Schnittstelle, für die nur eine abstrakte Methode definiert ist und die einem Lambda-Ausdruck zugeordnet ist.
    Verwenden Sie es grundsätzlich mit der Annotation @FunctionalInterface.
  2. Lambda-Typ: Es wird verwendet, um den Verarbeitungsinhalt über die Funktionstypschnittstelle zu implementieren und zu beschreiben.
    Die grundlegende Syntax lautet (Argument) -> {Verarbeitung}, und das Syntaxformat basierend auf der Anzahl der Argumentteile lautet 1 Argument: (str) -> {Verarbeitung}, 2 Argumente: (str1, str2) -> {Verarbeitung }.
    Die Grundform des Verarbeitungsteils ist {Anweisung 1; Anweisung 2;… Rückgabewert zurückgeben;}, und da es sich um einen Ausdruck handelt, ist es möglich, den Wert zurückzugeben.
    In neuen Methoden in Java8 ist es möglich, diesen Lambda-Ausdruck als Argument zu übergeben, was eine einfache Programmierung ermöglicht. Wenn Sie den Verarbeitungsteil beschreiben, der keine Nebenwirkungen hat, kann die ursprüngliche Funktionsprogrammierung in diesem Teil realisiert werden.
    Ähnlich wie in der vorherigen anonymen Klasse.
  3. Deklarative Programmierung: Es ist eine Programmiermethode, die eine Ausgabe erhält, indem der Zweck, die Eigenschaften, die Einschränkungen usw. beschrieben werden, ohne die Verarbeitungsprozedur (Daten und Algorithmus) zum Erhalten der Ausgabe zu beschreiben.
    Es kann sich auch auf einen allgemeinen Begriff für mehrere Sprachen beziehen, beispielsweise für reine Funktionssprachen.
    Einfach ausgedrückt ist es eine Programmiermethode, die festlegt, was benötigt wird, und es der Sprache, API, Funktionen usw. überlässt, um damit umzugehen.
  4. Funktion höherer Ordnung: Eine Funktion, die andere Funktionen als Argumente oder als Ergebnis zurückgeben kann.
    In Java8 gibt es Map, FlatMap, Filter, Reduce, forEach, anyMatch, allMatch und so weiter.
  5. StreamAPI: Es ist eine API, die Aggregate wie Arrays und Sammlungen verarbeitet und Werte aggregieren und mithilfe von Daten verarbeiten kann.
    Dies ist eine neue Funktion von Java 8.
  6. Optional: Optional ist eine Funktion, die Werte mit Nullen umschließt und Nullen sicher behandelt.
  7. Methodenreferenz: Das Zuweisen der Methode selbst zu einer Variablen in der Funktionsschnittstelle wird als Methodenreferenz bezeichnet.
    Die Anzahl und der Typ der Argumente der abstrakten Methode in der Funktionstypschnittstelle müssen jedoch mit der Anzahl und dem Typ der Argumente der Methode übereinstimmen, die Sie zuweisen möchten.
    Das Merkmal der Methodenreferenz ist, dass Sie eine definierte Methode ohne Argument aufrufen können und "Klassenname :: Methodenname" die Grundform ist.
    Es ist auch möglich, vordefinierte Methoden wie Lambda-Ausdrücke zu behandeln.
    (Beispiel)
    Beispiel 1: list.forEach (System.out :: print);
    Beispiel 2: Consumer c = System.out :: println;
        c.accept("abc");
    • Nebenwirkungen: Dies bedeutet, dass sich andere Dinge als die als Eingabe empfangenen Daten (variable Werte usw.) ändern (Statusänderung) und die nachfolgenden Ergebnisse beeinflussen.
      Bezieht sich auf Zuweisung, Inkrementieren, Dekrementieren, Eingabe / Ausgabe usw.
  8. Referenztransparenz (Referenztransparenz): Die Eigenschaft, immer das gleiche Ergebnis zurückzugeben, wenn die Eingabe gleich ist.
  9. Verzögerungsbewertung: Es ist einfach, eine sich wiederholende Struktur durch eine Berechnungsmethode einzubauen, bei der der Wert erst berechnet wird, wenn er benötigt wird.
    In Java8 wird die Verzögerungsauswertung in der Stream-API lokal unterstützt, und in der Stream-API wird keine spezifische Berechnung in der Generierungsverarbeitungsanweisung / Zwischenverarbeitungsanweisung und der Beendigung durchgeführt. Es ist so konzipiert, dass es zu dem Zeitpunkt ausgeführt wird, zu dem die Verarbeitungsanweisung gegeben wird. Darüber hinaus ist auch eine Verzögerungsverarbeitung unter Verwendung eines Lambda-Ausdrucks möglich.
    • Monade: Monade ist ein Mechanismus, eine Struktur und ein Konzept, mit denen Funktionen programmgesteuert kombiniert, synthetisiert und ausgeführt werden können.
      Es wird allgemein gesagt, dass es schwierig ist, die Details einschließlich des Konzepts zu verstehen, aber es gibt eine Meinung, dass es nicht schwierig ist. Es scheint viele Meinungen zu geben, dass die Anweisungen ziemlich schwierig sind.

[Zusätzliche Erklärung von Monad] Lassen Sie uns eine zusätzliche Erklärung zu Monad aus Programmsicht schreiben. "Monade" ist ein allgemeiner Begriff für verschiedene Arten von Monaden (Monadeninstanzen) und eine Typklasse in Haskell (funktionale Sprache). Die Standardmonaden sind: Vielleicht Monade, Listenmonade, Identitätsmonade, Entweder Monade, Staatsmonade, IO-Monade, Schriftsteller-Monade, Lesermonade, ... (In Haskell wird es auch als Vielleicht-Typ, Listentyp, ... bezeichnet.) Um eine Monade zu werden, müssen Sie die folgenden drei Bedingungen erfüllen. Wenn diese Bedingung erfüllt ist, kann sie als Monade bezeichnet werden. (1) Erhalten Sie ein Typargument. (2) Es kann durch Return and Bind (>> = Operator) betrieben werden. return ist eine Funktion, um einen Wert in die Monade zu setzen. bind ist ein Operator zum Übergeben des Werts der Monade an die Funktion. Er wird als monad >> -Funktion beschrieben und der Rückgabewert wird in die Monade eingefügt. (3) Erfüllen Sie die festgelegten Monadenregeln. Wenn Sie die Bedingungen erfüllen, handelt es sich um eine Monade, sodass Sie Ihre eigenen erstellen können, indem Sie die folgenden Schritte ausführen. (1) Definieren Sie den Typ als Monade. (2) Definieren Sie eine Instanz von Monad. (Beinhaltet Return- und Bind-Implementierungen.) Der Hauptzweck dieser Monade ist Monadenwert >> = Monadentypfunktion 1 >> = Monadentypfunktion 2 >> = Monadentypfunktion 3 ---> Monadenwert abrufen Ist in der Lage zu sein, Funktionen kontinuierlich auszuführen, wie. In Monad ist es auch möglich, beim Kombinieren eine Verarbeitung hinzuzufügen. Monadenwert: Der Wert, den die Monade hat. Monadentypfunktion: Eine Funktion, die einen Monadenwert empfängt und das Verarbeitungsergebnis als Monadenwert zurückgibt. Insbesondere können Monaden wie folgt verwendet werden. (Es ist nur ein Beispiel. Die Sprache ist Haskell.)

*> let addOne x = Just (x + 1) - Definition der Funktion addOne (Just bedeutet, dass es sich um den Wert von Maybe monad handelt) *> let addTwo x = Just (x + 2) - Definition der Funktion addTwo *> return 2 >> = addOne >> = addTwo --Kann 2 in die Monade einfügen und die Funktionen addOne und addTwo ausführen

Ergebnis: Nur 5 Dies ist ein Beispiel für die Verwendung der Vielleicht-Monade zum Kombinieren von zwei Funktionen, wobei >> = der Operator zum Kombinieren ist. Die endgültige Rückgabe 2 >> = addOne >> = addTwo kann auch im folgenden Format angegeben werden.   do return 2    addOne    addTwo Ich denke, die folgenden Schritte sind gut, um Monad besser zu verstehen.

Ich habe Haskell übrigens noch nie benutzt.


Monadendefinition
class Monad m where  return :: a -> m a  (>>=) :: m a -> (a -> m b) -> m b  (>>) :: m a -> m b -> m b  x >> y = x >>= \_ -> y  fail :: String -> m a  fail msg = error msg

Schließlich##

das ist alles. Vielen Dank für das Lesen bis zum Ende.

Recommended Posts

~ Ich habe jetzt versucht, funktionale Programmierung mit Java zu lernen ~
Ich habe jetzt versucht, Java 8 zusammenzufassen
Ich habe versucht, neunundneunzig in Java auszugeben
Ich habe versucht, Alexa-Fähigkeiten mit Java zu erstellen
Ich habe versucht, Metaprogrammierung mit Java
Ich habe versucht, die Firebase-Push-Benachrichtigung in Java zu implementieren
# 2 [Anmerkung] Ich habe versucht, neunundneunzig mit Java zu berechnen.
Ich habe versucht, eine Clova-Fähigkeit in Java zu erstellen
Ich habe versucht, die Methode der gegenseitigen Teilung von Eugrid in Java zu implementieren
Ich habe versucht herauszufinden, was sich in Java 9 geändert hat
Einführung in die funktionale Programmierung (Java, Javascript)
Wie man JAVA in 7 Tagen lernt
Ich habe versucht, mit Java zu interagieren
Ich habe versucht, JWT in Java zu verwenden
Ich habe versucht, Dapr in Java zu verwenden, um die Entwicklung von Mikroservices zu erleichtern
Ich habe einen RESAS-API-Client in Java erstellt
Ich habe versucht, die Elasticsearch-API in Java zu verwenden
Verstehen Sie, wie die funktionale Programmierung in Java auf einen Schlag eingeführt wurde
Ich habe versucht, Java-Lambda-Ausdrücke zusammenzufassen
Ich habe das neue Yuan-Problem in Java ausprobiert
Ich habe versucht, Java-Anfänger so einzustellen, dass sie Tastenkombinationen in Eclipse verwenden
Ich habe versucht, eine Android-Anwendung mit MVC zu erstellen (Java)
Ich habe versucht, mit AI "A3RT" eine Talk-App in Java zu erstellen.
Ich habe versucht, polymorph in Nogizaka zu implementieren.
Ich möchte eine E-Mail in Java senden.
Ich habe versucht, die Sitzung in Rails zu organisieren
Java Ich habe versucht, einen einfachen Block zu brechen
Ich wollte (a == 1 && a == 2 && a == 3) in Java wahr machen
rsync4j - Ich möchte rsync in Java berühren.
[Ruby-Grundlagen] Ich habe versucht, Module zu lernen (Kapitel 1)
Ich habe versucht, eine Anwendung in 2 Sprachen zu entwickeln
Ich habe versucht, den Block mit Java zu brechen (1)
Einschränkungsprogrammierung in Java
Versuchte Mastodons Toot- und Streaming-API in Java
Ich möchte so etwas wie "cls" in Java machen
Ich habe versucht, TCP / IP + BIO mit JAVA zu implementieren
[Java 11] Ich habe versucht, Java auszuführen, ohne mit Javac zu kompilieren
[Java] Ich habe versucht, Paizas B-Rang-Problem zu lösen
Ich habe versucht, SQS mit AWS Java SDK zu betreiben
Ich möchte ES2015 auch in Java verwenden! → (´ ・ ω ・ `)
Ich habe versucht, Sterling Sort mit Java Collector zu implementieren
[Java] Ich habe versucht, die Yahoo API-Produktsuche zu implementieren
Ich habe versucht, die erweiterte for-Anweisung in Java zu verwenden
Ich habe versucht, Java Silver in 2 Wochen zu bestehen, ohne Java zu kennen
Ich habe versucht, Effective Java 3rd Edition "fast alle Kapitel" in "leicht lesbarem Japanisch" zu erklären.
Probieren Sie den Funktionstyp in Java aus! ①
Ich habe ein Roulette in Java gemacht.
Ich habe Drools (Java, InputStream) ausprobiert.
Ich habe versucht, Java REPL zu verwenden
Implementieren Sie eine funktionsähnliche schnelle Sortierung in Java
Java8 startet jetzt ~ Optional ~
Ich habe versucht, yum-cron zu verifizieren
[Java] Grundbegriffe der Programmierung
Ich habe versucht, mit Chocolatey eine Java8-Entwicklungsumgebung zu erstellen
Ich habe versucht, eine Java EE-Anwendung mit OpenShift zu modernisieren.
[JDBC] Ich habe versucht, von Java aus auf die SQLite3-Datenbank zuzugreifen.
Ich habe versucht, die Grundlagen von Kotlin und Java zusammenzufassen