~ J'ai essayé d'apprendre la programmation fonctionnelle avec Java maintenant ~

Un an s'est écoulé depuis la publication, je n'ai donc pas changé l'essence du contenu, je l'ai revu et mis à jour en me concentrant sur l'ajout d'explications sur la source de la présentation.

Introduction

Cela fait plus de 4 ans que Java 8 a été publié en mars 2014, et il a été utilisé par de nombreuses personnes, notamment Java 9 et Java 10 et versions ultérieures. La programmation fonctionnelle est devenue un sujet brûlant lors de la sortie de Java 8. De nos jours, le terme programmation fonctionnelle est généralement reconnu et répandu parmi les développeurs de systèmes. Cependant, il semble que la pénétration réelle soit encore loin, car la situation actuelle est que nous ne voyons pas fréquemment les résultats du développement du système de la programmation fonctionnelle. Et, comme avec Java 8, les langages existants sont également améliorés en incorporant un style de programmation fonctionnel. Je ne peux pas prédire à quoi ressemblera le flux à l'avenir, mais je suppose personnellement que l'utilisation du style de programmation fonctionnelle dans les langages existants deviendra le courant dominant. Je pense qu'un langage fonctionnel pur sera un usage spécialisé, et dans le système Java, Scala ne remplacera pas le langage Java. La programmation fonctionnelle semble être dans une telle situation, mais on s'attend à ce qu'elle se propage d'une manière ou d'une autre à l'avenir, j'ai donc fait une étude générale et essayé de pratiquer la programmation simple dans l'environnement Java 10. .. De plus, j'ai décidé d'afficher les résultats d'apprentissage sous forme de mémorandum, pensant que cela pourrait être utile pour ceux qui sont intéressés. Veuillez noter que le contenu peut avoir une partie subjective ou un style de programme qui inclut une orientation personnelle. Pour les mots et expressions spécifiques à la programmation des fonctions, veuillez vous reporter aux brèves explications comprises dans la plage comprise à la fin. (* Mots avec des nombres)

Nouvelles fonctionnalités Java 8 ajoutées

Java 8 ajoute les nouvelles fonctionnalités suivantes pour la programmation de fonctions:

Avant d'entrer dans ces introductions, je voudrais essayer d'expliquer brièvement ce qu'est la programmation fonctionnelle en premier lieu.

Qu'est-ce que la programmation fonctionnelle?

Au sens strict, la programmation fonctionnelle est «une méthode de construction d'un programme avec des fonctions qui ont une transparence de référence (* 9) et aucun effet secondaire (* 8)», et cette définition est basée sur un langage fonctionnel. Cependant, il est maintenant possible de l'implémenter dans le style de programmation fonctionnelle même dans les langages existants, et ici nous avons décidé d'avoir une vision large de la programmation fonctionnelle et avons répertorié trois fonctionnalités.

  1. Simplifiez la programmation en tirant parti de la possibilité de passer une fonction (telle qu'une expression lambda) comme argument de fonction.
  2. Simplifiez la programmation et améliorez la qualité en utilisant diverses méthodes (fonctions) et grammaires pour la programmation fonctionnelle fournies par les langages et les API.
  3. Créez et utilisez des fonctions avec une transparence de référence (* 9) et sans effets secondaires, et développez la majeure partie du système en combinant les fonctions, en visant un système sûr et de haute qualité. On dit généralement que si la cible du problème peut être exprimée mathématiquement, presque toutes peuvent être développées avec des fonctions.

Je pense que créer un programme avec la méthode et le but mentionnés ci-dessus peut être reconnu comme une programmation fonctionnelle dans une large perspective. De plus, la programmation fonctionnelle n'est pas liée aux méthodes de développement telles que l'analyse des exigences et les processus de conception comme orienté objet, mais est destinée au processus de mise en œuvre du programme lui-même. Afin d'effectuer la programmation fonctionnelle, il y a ceux qui prennent en charge au niveau du langage comme Haskell et Scala, et ceux qui ajoutent une API pour la programmation fonctionnelle à un langage existant tel que Java 8. On dit que Java 8 peut couvrir la plage de 1 à 2, et Haskell et Scala peuvent couvrir la plage de 1 à 3. Un langage de programmation qui peut presque éviter les effets secondaires est également appelé un langage de programmation purement fonctionnel, et de ce point de vue, Scala's 3. est considéré comme un quasi-trois plutôt qu'un pur 3. Cependant, il va sans dire que cela dépend du projet s'il est nécessaire de configurer le système avec des «fonctions qui évitent presque les effets secondaires». La programmation fonctionnelle utilise une méthode pour créer une fonction relativement petite et l'appliquer ou la combiner pour développer un système basé sur le format de programmation déclarative (* 3). Par conséquent, pour mettre en œuvre le niveau 3, il est nécessaire de bien comprendre le concept de langage fonctionnel et de programmation fonctionnelle plutôt que la méthode de programmation orientée objet conventionnelle. En outre, il est nécessaire de bien comprendre à l'avance dans quelle mesure le problème cible correspond à la programmation fonctionnelle, telle que le système lié, le middleware de la plate-forme, le cadre de la plate-forme, les actifs accumulés associés et l'environnement de développement / gestion / opération. il y a. Les éléments suivants sont généralement répertoriés comme les avantages de la programmation fonctionnelle.

Il semble y avoir des situations au cas par cas pour les 4e et 5e items, mais il semble certain que la quantité de programmation sera réduite pour les parties applicables. D'autre part, l'inconvénient est que si le système de développement peut être exprimé mathématiquement, il est théoriquement possible de le développer avec une programmation de fonction pure, mais en réalité, il existe peu d'environnements de ce type, en particulier le traitement CRUD dans les systèmes d'entreprise. On dit qu'il n'y a pas beaucoup de mérite dans l'application principale. Java8 introduit de nouveaux mécanismes tels que les interfaces fonctionnelles, les expressions lambda, les flux et facultatif pour prendre en charge la programmation fonctionnelle. Cela permet d'écrire une partie de la programmation pédagogique traditionnelle dans un style de programmation fonctionnelle (programmation déclarative). Et lors de la programmation fonctionnelle avec ce Java 8 ou version ultérieure,

  1. Utilisez dans la mesure du possible de nouvelles API basées sur la programmation orientée objet. (Quantité de codage principalement réduite)
  2. Allez un peu plus loin et implémentez la méthode en créant et en utilisant une fonction avec une transparence de référence (de préférence sans effets secondaires) dans la mesure du possible. (Quantité de codage réduite et qualité améliorée)

Je pense qu'il y a deux cas, mais personnellement, je pense qu'il vaut mieux faire des pas (1) → (2) pour apprendre. Une chose à garder à l'esprit est que la programmation fonctionnelle ne fonctionne que sur Java 8 et supérieur. Afin de pouvoir fonctionner avec des versions plus anciennes de Java telles que Java6 et Java7, il est nécessaire de développer avec la programmation pédagogique comme auparavant, pas avec la programmation fonctionnelle.

Présentation des nouvelles fonctionnalités de Java 8

Les principales méthodes nouvelles et mises à jour liées à la programmation fonctionnelle dans Java 8 sont les suivantes. Ces méthodes sont utilisées pour tirer parti des fonctionnalités de base de la programmation fonctionnelle. Je pense que cela peut être exprimé comme l'incorporation de la programmation fonctionnelle dans un langage orienté objet. Vous pouvez facilement trouver les détails de chacune de ces méthodes en ligne ou dans des livres. Ici, nous donnerons un aperçu de chaque méthode et un échantillon de méthodes typiques.

・ Interface fonctionnelle Les expressions Lambda et les références de méthode (* 7) peuvent être utilisées à l'aide de l'interface fonctionnelle. Vous pouvez créer les vôtres, mais plusieurs interfaces fonctionnelles standard sont disponibles.

(): Nom de la méthode principale, type d'argument → type de retour Ce qui suit est une définition simple et un exemple d'utilisation d'une interface de type de fonction personnalisée.

[Description de code associé à l'exemple d'interface] -Un programme qui spécifie un nom de passe-temps et affiche "mon passe-temps: nom de passe-temps". -L'interface fonctionnelle IHobby avec la méthode abstraite getHobby (valeur de retour: chaîne de caractères) est définie de 009 à 012. -En 003 à 005, l'implémentation du traitement de IHobby est définie à l'aide de l'expression lambda. -La méthode getHobby de IHobby est exécutée en 006.

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 }

Vous trouverez ci-dessous un exemple simple d'utilisation de l'interface fonctionnelle standard Function.

[Description du code lié à LambdaParameter] -Un programme qui multiplie la valeur spécifiée par 5 et la produit. -La méthode getFiveTimes (valeur de retour: type entier) qui multiplie la valeur par 5 est définie entre 016 et 018. -La méthode d'exécution est exécutée de 007 à 009 pour obtenir la valeur 5 fois. -L'expression lambda du deuxième argument défini en 012 de 007 à 009 est reçue par l'interface fonctionnelle. -La méthode apply de l'interface fonctionnelle est exécutée en 013.

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("résultat:" + res);
011   }

      /**
      *Interface de la fonction d'argument(Style Lambda)Méthode à exécuter
      */
012   public static <R> R execute(Integer value, Function<Integer, R> fnc) {
013     R rtnval = fnc.apply(value);
014     return rtnval;
015   }

      /**
      *Méthode pour exécuter le traitement du béton(Multipliez la valeur par 5)
      */
016   public static Integer getFiveTimes(Integer value) {
017     return value * 5;
018   }

019 }

・ Carte De nouvelles méthodes ont également été ajoutées à la classe Map existante. Les principales méthodes ajoutées sont forEach, replaceAll, computeIfAbsent, computeIfPresent, compute et merge.

Voici un exemple simple. (k: clé de mappage v: valeur de mappage p: clé de valeur d'argument: clé spécifiée)

[Description du code associé à la carte] Le type de carte est String, String. ・ ForEach (001): Sort tous les éléments de la carte au format [Clé: Valeur]. ・ ReplaceAll (002 ~): Remplacez les valeurs de tous les éléments de la carte par null → [clé] et non nul → [clé + 2 premiers caractères de valeur]. ・ ComputeIfAbsent (008 ~): a. Si la clé existe dans la clé de mappage La valeur n'est pas mise à jour et la valeur est la valeur de retour. b. Si la clé existe et que la valeur est nulle La valeur est mise à jour en [clé + "-addition"] et cette valeur est la valeur de retour. c. S'il n'existe pas dans la clé Ajoutez une valeur avec la clé et la valeur [clé + "-addition"] au mappage, et cette valeur sera la valeur de retour. ・ ComputeIfPresent (011 ~): a. Si la clé existe dans la clé de mappage La valeur est mise à jour en [Clé + Valeur + "-addition"] et cette valeur est la valeur de retour. b. Si la clé existe et que la valeur est nulle La valeur n'est pas mise à jour et null est la valeur de retour. c. S'il n'existe pas dans la clé La valeur n'est ni ajoutée ni mise à jour et null est la valeur de retour. ・ Calculer (014 ~): a. Si la clé existe dans la clé de mappage La valeur est mise à jour en [Clé + Valeur + "-addition"] et cette valeur est la valeur de retour. b. Si la clé existe et que la valeur est nulle La valeur est mise à jour en [clé + valeur (null) + "-addition"], et cette valeur est la valeur de retour. c. S'il n'existe pas dans la clé Ajoutez l'élément (clé, [clé + valeur (null) + "-addition"]) à la carte, et cette valeur sera la valeur de retour. ・ Fusionner (017 ~): a. Si la clé existe dans la clé de mappage La valeur est mise à jour en [Value + "-add"] et cette valeur est la valeur de retour. b. Si la clé existe et que la valeur est nulle La valeur est mise à jour en ["-add"](en ignorant les valeurs nulles) et cette valeur est la valeur de retour. c. S'il n'existe pas dans la clé Ajoutez l'élément (clé, ["-add"]) (ignorez la valeur nulle) à la carte, et cette valeur sera la valeur de retour.

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);

· Liste De nouvelles méthodes ont également été ajoutées à la classe List existante. Les principales méthodes ajoutées sont forEach, removeIf, replaceAll, stream et parallelStream.

Voici un exemple simple. (v: valeur de la liste valeur: valeur externe)

[Description du code associé à la liste] Le type de liste est String. ・ ForEach (001): Affiche les valeurs de tous les éléments de la liste. ・ RemoveIf (002 ~): Il y a une valeur spécifiée dans la liste: L'élément correspondant est supprimé et true est renvoyé. b. La valeur spécifiée est null: l'élément correspondant n'est pas supprimé et false est renvoyé. c. Aucune valeur spécifiée: l'élément n'est pas supprimé et false est renvoyé. ・ ReplaceAll (008 ~): Valeur non nulle pour tous les éléments: mise à jour avec les 2 premiers caractères de la valeur. b. Valeur nulle pour tous les éléments: la valeur n'est pas mise à jour. ・ Trier (014): Un tri par ordre naturel / valeur maximale nulle est effectué pour tous les éléments. ・ Flux (015): a. Obtenez le flux de la liste. ・ ParallelStream (016): a. Obtenez un flux parallèle de liste.

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();

・ API Stream Il s'agit d'une API pour la gestion des tableaux et des collections, et peut être utilisée pour le traitement de données tel que l'agrégation de valeurs. Les méthodes de flux sont classées en deux types, l'un pour le traitement intermédiaire et l'autre pour le traitement de fin, en fonction du contenu de l'opération. Exécutez la méthode de traitement de fin via 0 ou plusieurs méthodes de traitement intermédiaires. Une API Stream primitive est également disponible. Méthode de traitement intermédiaire asDoubleStream、asLongStream、boxed、distinct、filter、flatMap、flatMapToDouble、flatMapToInt、flatMapToLong、limit、map、mapToDouble、mapToInt、mapToLong、mapToObj、onClose、parallel、peek、sequential、skip、sorted、unordered Ce qui suit est une brève description des méthodes typiques.

Voici un exemple simple. (flux: instance de flux v: liste de valeurs de flux: liste externe numlimit: valeur externe)

[Description du code lié au flux (traitement intermédiaire)] Le type de flux est Integer. ・ Filtre (001 ~): a. Stream Extrait des multiples de 3 pour tous les éléments et renvoie avec Stream . ・ Carte (004): Le nom du fichier de chaîne est stocké dans la liste, qui est convertie de liste en flux. b. Après cela, après la conversion en Stream , cette valeur est renvoyée. ・ FlatMap (005 ~): Traitement du contenu: Pour chaque élément de la liste, une copie avec "abc" au début est créée et renvoyée. Un caractère demi-largeur + un chiffre du nombre est stocké dans la liste, et un tableau de ["abc" + valeur] est créé pour le nombre de nombres. b. Ensuite, convertissez ce tableau en type Stream. De plus, cette valeur est convertie en List . ・ Distinct (010): a. Stream Tous les éléments sont renvoyés avec le même type, éliminant les éléments en double. ・ Trié (011): Le nombre total d'éléments dans le flux est trié par ordre croissant et renvoyé dans le même type. ・ Limite (012): Le nombre total d'éléments dans le flux est limité à numlimit et renvoyé avec le même type.

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);

Méthode de résiliation allMatch、anyMatch、average、collect、count、findAny、findFirst、forEach、forEachOrdered、iterator、max、min、noneMatch、reduce、spliterator、sum、summaryStatistics、toArray Voici une brève description des méthodes typiques.

Voici un exemple simple. (flux: instance de flux v: tableau de valeurs de flux: tableau externe ac: accumulateur)

[Description du code lié au flux (traitement de fin)] ・ AllMatch (001 ~): Le flux est vérifié sous la condition de correspondance totale (0 10). Renvoie true si tous les éléments correspondent. ・ AnyMatch (007 ~): a. Le flux est vérifié avec n'importe quelle condition (= 5). : Si une ou plusieurs correspondances, true est renvoyé. ・ Collecter (010 ~): Exemple 1: conversion d'un tableau en flux et utilisation de la méthode toList de la classe Collectors pour renvoyer le type List. La classe Collectors a plusieurs méthodes pour convertir du flux en d'autres classes. b. Exemple 2: Conversion d'une liste en flux, stockage de la valeur du flux dans un StringBuilder et retour du même type. (La signification réelle du troisième argument n'est pas dans ce cas. Il a généralement une signification dans le cas du traitement parallèle.) La description de l'argument de la méthode de collecte est la suivante.

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:(Plusieurs types existent)
010   //Exemple 1:Arrays.stream(array).collect(Collectors.toList());
011   //Exemple 2:list.stream().collect(StringBuilder::new, (b, v) -> b.append(v), (b1, b2) -> b1.append(b2));
      //1er argument:Génération d'objet de stockage de résultat, 2ème argument:Stocker la valeur du flux 3ème argument:Jointure d'objet
    count:
012   list.stream().count();
    reduce:(Plusieurs types existent)
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);

· Optionnel Facultatif est une classe qui encapsule une valeur. Vous pouvez vérifier les valeurs nulles et les valeurs. Facultatif.ofNullable, Facultatif.empty (), opt.isPresent (), ...

Exemple de programmation fonctionnelle en Java 8

Il existe de nombreux échantillons de plusieurs lignes sur le net et les livres, mais ici je vais vous présenter un exemple de niveau avec une certaine fonction. Cependant, la programmation de fonctions n'est pas quelque chose qui devrait être fait comme ça, mais est créée dans la perspective du codage de référence pour une compréhension rudimentaire. Les fonctions sont la gestion des stocks de produits et se composent de deux classes, la classe principale et la classe FunctionStock. Veuillez noter que la classe FunctionStock présente formellement autant d'exemples d'utilisation d'API que possible, de sorte que la programmation fonctionnelle est effectuée même là où elle n'est pas nécessaire. Aperçu de la classe StockMain: La classe principale de la gestion des stocks. Nous ne faisons pas de programmation fonctionnelle. FunctionStock: une classe qui traite réellement l'inventaire. Je fais de la programmation fonctionnelle avec plusieurs méthodes. IStock: interface de classe de traitement d'inventaire. IStockExecuter: interface de fonction Homebrew pour le traitement des stocks. Veuillez vous référer au commentaire de la classe principale pour la fonction détaillée et le commentaire du plan de méthode. Le type de programmation fonctionnelle utilisé par la marque ☆ est décrit.

[Description du code associé à StockMain] Les cartes qui stockent le nombre de stocks et les configurations d'accessoires sont définies de 013 à 014. De 025 à 036, 6 articles et la quantité de stock initiale sont définis. cd et magazine ont des accessoires. Le traitement spécifique est défini entre 016 et 022. Le livre définit deux processus d'achat et un processus de vente. magazine définit un processus de vente. Enfin, le processus de sortie de la liste d'inventaire est défini. 037 à 046 exécutent le processus d'achat avec la méthode du stock. 047 à 056 exécutent le traitement des ventes avec la méthode de vente. La quantité est négative. 057 à 066 sortent la quantité en stock du produit spécifié par la méthode get. 067 à 076 sortent la liste d'inventaire des produits avec la méthode getList. Le traitement des achats, le traitement des ventes, la sortie de la quantité d'inventaire et la sortie de la liste d'inventaire sont tous exécutés par la méthode d'exécution de FunctionStock.

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;

    /**
     *Classe principale de gestion des stocks
     *Fonction: processus d'achat(stock), Traitement des ventes(sale), Traitement des contrôles d'inventaire(get), Traitement de la sortie de la liste d'inventaire(getList)
     * (): Nom de la méthode
     *Format de traitement des données de stock: nom de la méthode(Nom du produit,quantité)
     *Accessoires pour chaque produit(Plusieurs possibles, mais chaque quantité est limitée à une)Est attaché, et l'inventaire de ses accessoires est également géré.
     *Processus d'achat: Augmentez le nombre de produits spécifiés en stock par le nombre d'achats. Si le produit désigné n'est pas enregistré, le produit est également enregistré.
     *Traitement des ventes: réduisez le nombre de produits spécifiés en stock du nombre vendu. Cependant, s'il n'y a pas de stock avec accessoires, le traitement sera arrêté.
     *Traitement du contrôle des stocks: génère le nombre de produits spécifiés en stock.
     *Traitement de la sortie de la liste de stock: génère le nombre de stocks de tous les produits. La liste des accessoires est également sortie.
     *Traitement des erreurs: génère un message d'erreur lorsqu'il se produit et annule le traitement ultérieur.
     */
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; //Version JDK8
      //private static final boolean funcOption = false; //JDK6,Version JDK7

011   public static void main(String[] args) {
012     System.out.println("**start**");
        //
        //Définir la valeur initiale de la carte
013     stockMap = new TreeMap<String, Integer>();
014     subStockMap = new TreeMap<String, List<String>>();
015     setInitialMap();
        //
        //Traitement des données d'inventaire
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   }

      /**
      *Méthode pour définir la valeur initiale de la carte
      */
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   }

      /**
      *Méthode pour effectuer le processus d'achat
      */
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   }

      /**
      *Méthode de traitement des ventes
      */
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   }

      /**
      *Méthode de sortie de la quantité en stock du produit spécifié
      */
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   }

      /**
      *Méthode de sortie de la liste d'inventaire
      */
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   }

      /**
      *Méthode pour définir la carte en objet de stock
      */
077   private static void setMap() {
078     stockObject.setStockMap(stockMap);
079     stockObject.setSubStockMap(subStockMap);
080   }
081 }

[Description du code lié au stock de fonction] Pour 028 à 042, productName, quantité et type sont définis entre 013 et 014 dans le constructeur. type représente le type de traitement et add, delname, get et getlist peuvent être spécifiés. ・ Exécuter la méthode Les données de stock spécifiées sont sorties pour confirmation à 044. Vérification des données de stock spécifiées de 045 à 048. Vérifiez les données d'inventaire avec la méthode getDataCheckFunction (). Get (), obtenez le résultat sous forme de chaîne, convertissez-le en facultatif avec Optional.ofNullable, faites un jugement null facultatif avec ifPresent et affichez une erreur avec outputErrorMessage s'il y a une erreur. Je vais. En 052, le traitement des données d'inventaire est exécuté par la méthode executeStock (). Execute () (interface de fonction auto-fabriquée IStockExecuter) et le résultat du traitement est stocké dans le type générique facultatif: Integer. En 053, le message d'erreur dans le traitement des données d'inventaire est généré par la méthode getErrorKeyFunction (). Apply (result) et sorti par outputErrorMessage. -GetDataCheckFunction, méthode 066 à 078 définit l'implémentation d'une interface fonctionnelle (type générique fournisseur: chaîne) qui vérifie les données d'inventaire (contrôle nul, etc.). ・ Méthode ExecuteStock 079 à 096 définissent une implémentation d'interface fonctionnelle (de IStockExecuter) qui traite les données d'inventaire (types de traitement: add, delname, get, getlist). Il appelle updateStock (). Get (), deleteStockName (). Get (), getStock (). Get (), outputStockList (getStockList (). Get ()), outputSubStockList (). ・ Méthode UpdateStock 097 à 126 définissent la mise en œuvre d'une interface fonctionnelle (type générique fournisseur facultatif) qui met à jour le nombre de stocks. La quantité en stock est mise à jour à l'aide de la méthode addToStockMap (). Apply (・ ・). ・ Méthode AddToStockMap Définit l'implémentation d'une interface de type de fonction (type générique BiFunction: String, Integer, Optional) qui met à jour spécifiquement le nombre de stocks de 127 à 138. La méthode de calcul de Map est utilisée pour augmenter ou diminuer le nombre de stocks. -DeleteStockName méthode 139 à 147 définissent la mise en œuvre d'une interface fonctionnelle (type générique fournisseur: facultatif) qui supprime les articles à stocker (données de stock). La méthode de suppression de Map est utilisée pour supprimer les articles en stock. ・ Méthode GetStock 148 à 154 définissent la mise en œuvre d'une interface fonctionnelle (type générique fournisseur: optionnel) qui acquiert le nombre de stocks d'un article spécifique. La quantité en stock est acquise à l'aide de la méthode getOrDefault de Map. ・ Méthode GetStockList Définit l'implémentation d'une interface fonctionnelle (type générique fournisseur: chaîne) qui récupère la liste des quantités en stock de 155 à 166. La liste d'inventaire est générée à l'aide de la méthode forEach de Map. -GetErrorKeyFunction, méthode 167 à 175 définissent l'implémentation d'une interface de type de fonction (Type générique de fonction: facultatif, chaîne) qui vérifie le résultat du traitement d'inventaire. La méthode de mappage facultative (errindex) définit la génération de message en cas d'erreur. -OutputSubStockList méthode Une liste d'accessoires est sortie de 191 à 204. Les informations de sortie d'accessoire pour un élément spécifique sont générées par la méthode de collecte après la conversion de liste en flux. -OutputErrorMessage, méthode Les messages d'erreur sont émis pour messageKey de 205 à 220. Après avoir converti messageKey en facultatif, un message d'erreur est généré par la méthode map.

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;

    /**
     *Classe de gestion des stocks
     */
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   "★ Le nom du produit n'est pas spécifié.",
023   "★ Le nom du produit spécifié dans la liste d'inventaire n'existe pas.",
024   "★ La quantité n'est pas spécifiée.",
025   "★ La quantité de stock sera inférieure à zéro.<%p1%> <%p2%>Pièces",
026   "★ La quantité d'accessoires en stock sera inférieure à zéro.<%p1%> <%p2%>Pièces",
027   "★ La clé est anormale.");

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

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

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

      /**
      *Méthode de traitement des données d'inventaire
      *☆ Utilisez les méthodes facultatives des méthodes Nullable, ifPresent et orElse
      *☆ Utilisez la méthode apply de l'interface Function
      */
043   public int execute() {
        //Sortie des données d'inventaire
044     outputData();
        //Vérification des données d'inventaire
045     Optional.ofNullable(getDataCheckFunction().get()).ifPresent(ekey -> {
046       outputErrorMessage(ekey);
047       errorKey = ekey;
048     });
049     if (null != errorKey) {
050       return -1;
051     }
        //Traitement des données d'inventaire
052     Optional<Integer> result = executeStock().execute();
        //Sortie d'erreur
053     outputErrorMessage(getErrorKeyFunction().apply(result));
054     return result.orElse(-1);
055   }

      /**
      *Méthode de sortie des données d'inventaire
      */
056   private void outputData() {
057     StringBuilder sb = new StringBuilder();
058     sb.append("Données en cours:");
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   }

      /**
      *Méthode de vérification des données d'inventaire
      *☆ Utilise l'interface fonctionnelle Fournisseur
      */
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   }

      /**
      *Méthode de traitement des données d'inventaire
      *☆ Utilisez l'interface de type de fonction personnalisée IStockExecuter
      *☆ Utilisez la méthode vide facultative
      */
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   }

      /**
      *Méthode de mise à jour de la quantité de stock(Peut être augmenté ou diminué)
      *☆ Utilise l'interface fonctionnelle Fournisseur
      *☆ Utilisez la méthode apply de l'interface fonctionnelle BiFunction
      *☆ Utilisation facultative de la méthode
      *☆ Utilisez la liste pour chaque méthode
      *☆ Utilisez la méthode getOrDefault de 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   }

      /**
      *Méthode de mise à jour de la valeur en stock du produit
      *☆ Utilise l'interface fonctionnelle BiFunction
      *☆ Utilisez la méthode de calcul de Map
      *☆ Utilisation facultative de la méthode
      */
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   }

      /**
      *Méthode de suppression des données d'inventaire des marchandises
      *☆ Utilise l'interface fonctionnelle Fournisseur
      *☆ Utilisez facultatif deNullable, isPresent et des méthodes
      */
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   }

      /**
      *Méthode pour obtenir le nombre de stock
      *☆ Utilise l'interface fonctionnelle Fournisseur
      *☆ Utilisez la méthode getOrDefault de Map
      *☆ Utilisation facultative de la méthode
      */
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   }

      /**
      *Méthode pour générer la liste d'inventaire
      *☆ Utilise l'interface fonctionnelle Fournisseur
      *☆ Utilisez la méthode Map forEach
      */
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   }

      /**
      *Méthode de vérification du résultat du traitement des stocks
      *☆ Interface de type de fonction Utiliser la fonction
      *☆ Utilisez les méthodes optionnelles map et 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   }

      /**
      *Méthode de sortie du nombre de stocks
      */
176   private void outputNumberStock(int result) {
177     if (-1 < result) {
178       StringBuilder sb = new StringBuilder();
179       sb.append("☆ Quantité de stock du nom de stock spécifié:");
180       sb.append(productName);
181       sb.append(" ");
182       sb.append(result);
183       sb.append("Pièces");
184       System.out.println(sb.toString());
185     }
186   }

      /**
      *Méthode de sortie de la liste d'inventaire
      */
187   private void outputStockList(String list) {
188     System.out.println("☆ Liste d'inventaire");
189     System.out.println(list);
190   }

      /**
      *Méthode de sortie de la liste d'accessoires
      *☆ Utilisez les méthodes Map forEach et getOrDefault
      *☆ Utilisez la méthode de flux de List
      *☆ Utilisez la méthode de collecte de Stream
      */
191   private void outputSubStockList() {
192     System.out.println("☆ Liste d'accessoires");
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   }

      /**
      *Méthode de sortie du message d'erreur
      *☆ Utilisez facultatif des méthodes Nullable et 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("★ Le traitement a été annulé.");
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 }

Résumé de la mise en œuvre de la programmation fonctionnelle

Brève explication des termes liés à la programmation des fonctions

Ce qui suit est une brève explication des termes liés à la programmation de fonctions qui apparaissent souvent sur le net. Comme il est difficile de comprendre la monade, j'ai ajouté une explication supplémentaire.

  1. Interface fonctionnelle: Une interface qui n'a qu'une seule méthode abstraite définie et est associée à une expression lambda.
    En gros, utilisez-le avec l'annotation @FunctionalInterface.
  2. Type Lambda: Il est utilisé pour implémenter et décrire le contenu du traitement à l'aide de l'interface de type de fonction.
    La syntaxe de base est (argument) -> {processing}, et le format de syntaxe basé sur le nombre de parties d'argument est 1 argument: (str) -> {processing}, 2 arguments: (str1, str2) -> {processing }.
    La forme de base de la partie de traitement est {instruction 1; instruction 2;… valeur de retour de retour;}, et comme il s'agit d'une expression, il est possible de renvoyer la valeur.
    Dans les nouvelles méthodes de Java8, il est possible de passer cette expression lambda comme argument, ce qui permet une programmation simple. Si vous décrivez la partie de traitement qui n'a pas d'effets secondaires, la programmation fonctionnelle d'origine peut être réalisée dans cette partie.
    Similaire à la classe anonyme précédente.
  3. Programmation déclarative: C'est une méthode de programmation qui obtient la sortie en décrivant le but, les propriétés, les contraintes, etc. sans décrire la procédure de traitement (données et algorithme) pour obtenir la sortie.
    Il peut également faire référence à un terme général pour plusieurs langages tels que les langages fonctionnels purs.
    Pour faire simple, c'est une méthode de programmation qui définit ce qui est nécessaire et laisse le soin au langage, à l'API, aux fonctions, etc. de le gérer.
  4. Fonction d'ordre supérieur: Une fonction qui peut retourner d'autres fonctions comme arguments ou comme résultat.
    En Java8, il existe Map, FlatMap, Filter, Reduce, forEach, anyMatch, allMatch, etc.
  5. StreamAPI: Il s'agit d'une API qui gère des agrégats tels que des tableaux et des collections, et peut agréger des valeurs et traiter à l'aide de données.
    Il s'agit d'une nouvelle fonctionnalité de Java 8.
  6. Optional: Facultatif est une fonction qui encapsule les valeurs contenant des valeurs nulles et gère les valeurs nulles en toute sécurité.
  7. Référence de la méthode: L'affectation de la méthode elle-même à une variable dans l'interface fonctionnelle est appelée une référence de méthode.
    Cependant, le nombre et le type d'arguments de la méthode abstraite dans l'interface de type de fonction doivent correspondre au nombre et au type d'arguments de la méthode que vous souhaitez affecter.
    La caractéristique de la référence de méthode est que vous pouvez appeler une méthode définie sans aucun argument, et "nom de classe :: nom de méthode" est la forme de base.
    Il est également possible de traiter des méthodes prédéfinies comme des expressions lambda.
    (Exemple)
    Exemple 1: list.forEach (System.out :: print);
    Exemple 2: Consumer c = System.out :: println;
        c.accept("abc");
    • Effets secondaires: Cela signifie que des choses autres que les données reçues en entrée (valeurs de variables, etc.) changent (changement d'état) et affectent les résultats ultérieurs.
      Désigne l'affectation, l'incrémentation, la décrémentation, l'entrée / sortie, etc.
  8. Transparence de référence (transparence de référence): La propriété de toujours renvoyer le même résultat si l'entrée est la même.
  9. Évaluation des retards: Il est possible d'incorporer facilement une structure répétitive par une méthode de calcul dans laquelle la valeur n'est pas calculée tant qu'elle n'est pas nécessaire.
    Dans Java8, l'évaluation du retard est prise en charge localement dans l'API Stream, et dans l'API Stream, le calcul spécifique n'est pas effectué dans l'instruction de traitement de génération / l'instruction de traitement intermédiaire et l'arrêt. Il est conçu pour être exécuté au moment où l'instruction de traitement est donnée. De plus, le traitement différé à l'aide d'une expression lambda est également possible.
    • Monade: Monad est un mécanisme, une structure et un concept qui permettent aux fonctions d'être combinées, synthétisées et exécutées par programme.
      On dit généralement qu'il est difficile de comprendre les détails, y compris le concept, mais il y a une opinion que ce n'est pas difficile. Il semble qu'il y ait beaucoup d'avis que les instructions sont plutôt difficiles.

[Explication supplémentaire de Monad] Écrivons une explication supplémentaire sur Monad du point de vue du programme. "Monad" est un terme général pour plusieurs types de monades (instances de monades), et est une classe de types en Haskell (langage fonctionnel). Les monades standard sont: Peut-être monade, Monade de liste, Monade d'identité, Soit monade, Monade d'État, Monade IO, Monade d'écrivain, Monade de lecteur, ... (En Haskell, on l'appelle aussi type Maybe, type List, ...) Pour devenir une monade, vous devez remplir les trois conditions suivantes. Si cette condition est remplie, elle peut être appelée une monade. (1) Recevez un argument de type. (2) Il peut être actionné par return et bind (>> = opérateur). return est une fonction pour mettre une valeur dans la monade. bind est un opérateur pour passer la valeur de la monade à la fonction, et il est décrit comme monade >> fonction et la valeur de retour est placée dans la monade. (3) Satisfaire aux règles établies de la Monade. Si vous remplissez les conditions, ce sera une monade, vous pouvez donc créer la vôtre en suivant les étapes ci-dessous. (1) Définissez le type pour être une monade. (2) Définissez une instance de Monad. (Inclut les implémentations de retour et de liaison.) Le but principal de cette monade est Valeur Monade >> = Fonction de type Monade 1 >> = Fonction de type Monade 2 >> = Fonction de type Monade 3 ---> Obtenir la valeur de monade Est de pouvoir exécuter des fonctions en continu comme. Dans Monad, il est également possible d'ajouter des traitements lors de la combinaison. Valeur de la monade: valeur de la monade. Fonction de type monade: fonction qui reçoit une valeur monade et renvoie le résultat du traitement sous forme de valeur monade Plus précisément, les monades peuvent être utilisées comme suit. (Ce n'est qu'un exemple. La langue est Haskell.)

*> let addOne x = Just (x + 1) --Définition de la fonction addOne (signifie simplement que c'est la valeur de Maybe monad) *> let addTwo x = Just (x + 2) --Définition de la fonction addTwo *> return 2 >> = addOne >> = addTwo --Peut-être Mettre 2 dans la monade et exécuter les fonctions addOne et addTwo

Résultat: seulement 5 Voici un exemple d'utilisation de la monade Maybe pour combiner deux fonctions, où >> = est l'opérateur de combinaison. Le retour final 2 >> = addOne >> = addTwo peut également être spécifié dans le format suivant.   do return 2    addOne    addTwo Je pense que les étapes suivantes sont bonnes pour mieux comprendre Monad.

Au fait, je n'ai jamais utilisé Haskell.


Définition de la monade
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

Finalement##

c'est tout. Merci d'avoir lu jusqu'au bout.

Recommended Posts

~ J'ai essayé d'apprendre la programmation fonctionnelle avec Java maintenant ~
J'ai essayé de résumer Java 8 maintenant
J'ai essayé de sortir quatre-vingt-dix-neuf en Java
J'ai essayé de créer une compétence Alexa avec Java
J'ai essayé la métaprogrammation avec Java
J'ai essayé d'implémenter la notification push Firebase en Java
# 2 [Note] J'ai essayé de calculer quatre-vingt-dix-neuf avec Java.
J'ai essayé de créer une compétence Clova en Java
J'ai essayé d'implémenter la méthode de division mutuelle d'Eugrid en Java
J'ai essayé de découvrir ce qui avait changé dans Java 9
Introduction à la programmation fonctionnelle (Java, Javascript)
Comment apprendre JAVA en 7 jours
J'ai essayé d'interagir avec Java
J'ai essayé d'utiliser JWT en Java
J'ai essayé d'utiliser Dapr en Java pour faciliter le développement de microservices
J'ai créé un client RESAS-API en Java
J'ai essayé d'utiliser l'API Elasticsearch en Java
Comprendre comment la programmation fonctionnelle a été introduite dans Java d'un seul coup
J'ai essayé de résumer les expressions Java lambda
J'ai essayé le nouveau yuan à Java
J'ai essayé de configurer les débutants Java pour qu'ils utilisent des touches de raccourci dans eclipse
J'ai essayé de créer une application Android avec MVC maintenant (Java)
J'ai essayé de créer une application de conversation en Java à l'aide de l'IA «A3RT»
J'ai essayé d'implémenter des relations polymorphes à Nogizaka.
Je souhaite envoyer un e-mail en Java.
J'ai essayé d'organiser la session en Rails
java j'ai essayé de casser un simple bloc
Je voulais que (a == 1 && a == 2 && a == 3) vrai en Java
rsync4j --Je veux toucher rsync en Java.
[Notions de base sur Ruby] J'ai essayé d'apprendre des modules (Chapitre 1)
J'ai essayé de développer une application en 2 langues
J'ai essayé de casser le bloc avec java (1)
Programmation par contraintes en Java
Essayé l'API Toot et Streaming de Mastodon en Java
Je veux faire quelque chose comme "cls" en Java
J'ai essayé d'implémenter TCP / IP + BIO avec JAVA
[Java 11] J'ai essayé d'exécuter Java sans compiler avec javac
[Java] J'ai essayé de résoudre le problème de rang B de Paiza
J'ai essayé de faire fonctionner SQS en utilisant AWS Java SDK
Je veux aussi utiliser ES2015 avec Java! → (´ ・ ω ・ `)
J'ai essayé d'implémenter Sterling Sort avec Java Collector
[Java] J'ai essayé de mettre en œuvre la recherche de produits de l'API Yahoo
J'ai essayé d'utiliser l'instruction Extended for en Java
J'ai essayé de passer Java Silver en 2 semaines sans connaître Java
J'ai essayé d'expliquer Effective Java 3rd Edition "presque tous les chapitres" en "japonais facile à lire".
Essayez le type fonctionnel en Java! ①
J'ai fait une roulette à Java.
J'ai essayé Drools (Java, InputStream)
J'ai essayé d'utiliser Java REPL
Implémenter un tri rapide de type fonction en Java
Java8 pour démarrer maintenant ~ Facultatif ~
J'ai essayé de vérifier yum-cron
[Java] Termes de base en programmation
J'ai essayé de créer un environnement de développement java8 avec Chocolatey
J'ai essayé de moderniser une application Java EE avec OpenShift.
[JDBC] J'ai essayé d'accéder à la base de données SQLite3 depuis Java.
J'ai essayé de résumer les bases de kotlin et java