[Java] Différentes méthodes pour acquérir la valeur stockée dans List par traitement itératif

Première étape

Dans cet article, je présenterai quelques façons de faire fonctionner le traitement itératif en utilisant la structure de données de List quelle que soit l'implémentation.

Le contenu de l'article est au niveau du bon sens pour ceux qui programment habituellement en Java, le public cible est donc des débutants aux intermédiaires qui viennent de commencer à apprendre Java. Cependant, j'ai l'impression qu'il y a encore peu de personnes utilisant la méthode forEach qui a été ajoutée dans JDK 1.8 sur le site de développement, donc j'aimerais que vous vous rappeliez comment utiliser la méthode forEach pour le moment. ..

Notez que cet article traite des itérations simples à l'aide de la collection List, nous ne parlerons donc pas de l'API Stream, qui effectue des opérations intermédiaires telles que filtre. Je voudrais présenter l 'API Stream dans un autre article.

Ce que vous pouvez faire en lisant cet article

--Traitement itératif à l'aide de la collection List

Méthode d'opération du traitement itératif principal

Accès aléatoire en utilisant la méthode get

Depuis l'introduction de fonctions pratiques et efficaces telles que l'instruction ʻextended for et la méthode forEachdans JDK 1.8, il n'y a presque aucune situation où la méthodeget` est utilisée pour la collection List et le traitement itératif est effectué avec un accès aléatoire. J'ai fait. Cependant, cet accès aléatoire est la méthode itérative la plus basique utilisant la collection List, quelle que soit l'implémentation, alors n'oubliez pas de vous en souvenir si vous programmez avec Java.

La méthode de fonctionnement de base est la suivante.

import java.util.List;
import java.util.ArrayList;

public final class TestGet {

    public static void main(String[] args) {
        final List<String> testList = new ArrayList<>(3);
        testList.add("test1");
        testList.add("test2");
        testList.add("test3");

        for (int i = 0, size = testList.size(); i < size; i++) {
            //Récupère le i-ème élément de la variable (accès aléatoire)
            System.out.println(testList.get(i));
        }
    }
}

Dans l'exemple de code ci-dessus, nous implémentons d'abord une liste de test qui peut stocker trois éléments sous la forme ʻArrayList, puis ʻajouter les valeurs de test.

Après cela, utilisez l'instruction de base pour et répétez le processus pour la taille de testList préparé plus tôt. Dans l'exemple de code ci-dessus, la variable ʻiest incrémentée à chaque fois qu'elle est répétée, donc comme vous pouvez le voir dans les commentaires, le traitement detestList.get (i)est exécuté séquentiellement pour les éléments detestList`. Il sera accessible au hasard.

Par conséquent, le résultat de l'exécution de l'exemple de code ci-dessus est généré comme suit.

test1
test2
test3

point important

Lorsque vous utilisez l'accès aléatoire en utilisant la méthode get comme dans l'exemple de code ci-dessus, assurez-vous de vérifier la taille de la liste à laquelle accéder. Si vous spécifiez un index plus grand que la taille de la liste cible dans la méthode get, ʻIndexOutOfBoundsException` (exception hors limites) se produira toujours à l'exécution et le processus échouera.

Par exemple, dans les cas suivants.

import java.util.List;
import java.util.ArrayList;

public final class TestIndexOutOfBoundsException {

    public static void main(String[] args) {
        final List<String> testList = new ArrayList<>();
        testList.add("test1");
        testList.add("test2");
        testList.add("test3");

        //Spécifiez un quatrième index qui n'existe pas
        testList.get(3);
    }
}

Lorsque j'exécute l'exemple de code ci-dessus, j'obtiens l'exception suivante:

java.lang.IndexOutOfBoundsException: Index 3 out of bounds for length 3
    at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
    at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
    at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
    at java.base/java.util.Objects.checkIndex(Objects.java:373)
    at java.base/java.util.ArrayList.get(ArrayList.java:425)

La taille de la liste à accéder de façon aléatoire peut être obtenue avec la méthode size () comme indiqué dans l'exemple de code qui se termine normalement. Si vous pouvez toujours obtenir un seul enregistrement de la base de données basé sur une clé unique, utilisez la méthode size () sans vérifier la taille de la liste, comme `testList.get (0); Il est permis d'obtenir la valeur cible dans le processus.

Le point important est de clarifier la plage accessible afin que ʻIndexOutOfBoundsException` ne se produise pas lors de l'exécution lors de l'exécution d'un accès aléatoire.

Dans la collection Java List, il existe une structure de données appelée LinkedList, qui est également couramment utilisée comme ʻArrayList. Cette LinkedList` est un mécanisme qui contient le contexte des éléments stockés avec un lien, il devient donc une structure de données appropriée pour insérer de nouveaux éléments dans le tableau et supprimer les éléments dans le tableau.

Cependant, l'accès aléatoire à LinkedList a les pires performances. Si le nombre d'éléments à accéder de manière aléatoire est d'environ 100, le temps de traitement sera presque le même que lors de l'utilisation de ʻArrayList, mais avec LinkedList`, l'accès aléatoire est répété pour 100 000 ou plus de données à grande échelle. Ce n'est pas réaliste en termes de performances.

Par conséquent, lorsque vous manipulez des données à grande échelle avec LinkedList par un traitement itératif, utilisez un accès séquentiel tel que extended for statement et la méthode forEach, qui seront introduites plus tard, au lieu d'un accès aléatoire à l'aide de la méthode get. Pars s'il te plait.

De côté

L'exemple de code suivant pour l'accès aléatoire a été introduit plus tôt.

import java.util.List;
import java.util.ArrayList;

public final class TestGet {

    public static void main(String[] args) {
        final List<String> testList = new ArrayList<>(3);
        testList.add("test1");
        testList.add("test2");
        testList.add("test3");

        for (int i = 0, size = testList.size(); i < size; i++) {
            //Récupère le i-ème élément de la variable (accès aléatoire)
            System.out.println(testList.get(i));
        }
    }
}

Je pensais que l'instruction for dans l'exemple de code ci-dessus n'était peut-être pas familière aux débutants, je vais donc laisser une explication. Dans l'exemple de code ci-dessus, l'instruction for peut être écrite comme suit.

for (int i = 0; i < testList.size(); i++) {
    // do something
}

Dans l'exemple de code introduit au début, j'ai essayé d'obtenir la taille de testList en exécutant l'appel de la méthode size () qui se trouvait dans la partie expression d'initialisation dans la partie expression conditionnelle.

Cependant, vous devez éviter d'écrire la déclaration for ci-dessus. Ceci est dû au fait que la partie expression conditionnelle de l'instruction for ʻi <testList.size () est exécutée à chaque fois qu'un traitement itératif est effectué, donc dans le cas du code ci-dessus, la méthode size () est appelée par la taille de testList`. Ce sera. Environ 10 ou 100 auront peu d'impact sur les performances, mais même de petites différences peuvent faire une grande différence.

Par exemple, vous pouvez vérifier que le traitement de la partie d'expression conditionnelle est exécuté à chaque fois avec l'exemple de code suivant.

public final class Main {

    public static void main(String[] args) throws Exception {
        //Assurez-vous que la partie d'expression conditionnelle est exécutée à chaque fois
        for (int i = 0; i < 10 && saySomething(); i++) {
            // do something
        }
    }

    private static boolean saySomething() {
        System.out.println("Hello World!");
        return true;
    }
}

Le résultat de l'exécution de l'exemple de code ci-dessus est généré comme suit. Je n'écrirais pas de code comme celui ci-dessus dans mon développement normal, mais j'ai pu confirmer que la méthode saySomething () de la partie d'expression conditionnelle a été exécutée 10 fois.

Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!
Hello World!

À partir de ce qui précède, il est possible d'écrire un programme plus léger et plus efficace en recherchant le nombre d'observations à utiliser dans la partie expression conditionnelle de la partie expression d'initialisation qui n'est exécutée qu'une seule fois au début de l'instruction for. C'est une technique qui peut être appliquée non seulement à la méthode size () dans la collection List mais aussi à diverses situations, donc j'aimerais que les personnes qui visent un meilleur programme gardent à l'esprit chaque jour.

Accès séquentiel utilisant ʻextended for statement`

Cela fait un moment que l'instruction «étendue for» a été ajoutée en tant que fonctionnalité Java, et elle est déjà devenue la norme de facto pour le traitement itératif séquentiel des collections List. L'instruction for est également plus simple et plus efficace que celle pour l'accès aléatoire.

Avant l'introduction de l'instruction ʻextended for, l'accès séquentiel était réalisé en implémentant l'interface ʻIterator seule. L'accès séquentiel avec l'interface ʻIterator est compliqué et souvent implémenté, et il est rarement utilisé dans les styles d'écriture hérités, donc je ne le couvrirai pas en détail dans cet article, mais en tant que connaissance, avant l'apparition de ʻextended for statement Gardez à l'esprit que vous avez pu obtenir un accès séquentiel en implémentant vous-même l'interface ʻIterator`.

De plus, la dégradation des performances lors de l'utilisation de ʻIndexOutOfBoundsException et LinkedListintroduite lors d'un accès aléatoire à l'aide de la méthodeget ne se produit pas avec un accès séquentiel utilisant l'instruction extended for`.

Par conséquent, si vous pouvez utiliser l'instruction ʻextended for, ne répétez pas le processus avec un accès aléatoire et essayez d'écrire le processus itératif en utilisant l'instruction extended for`.

Maintenant, si vous réécrivez l'exemple de code pour un accès aléatoire à l'aide de la méthode get introduite précédemment avec un accès séquentiel à l'aide de l'instruction extended for, ce sera comme suit.

import java.util.List;
import java.util.ArrayList;

public final class TestEnhancedForStatement {

    public static void main(String[] args) {
        final List<String> testList = new ArrayList<>(3);
        testList.add("test1");
        testList.add("test2");
        testList.add("test3");

        for (String value : testList) {
            //Récupérez les valeurs stockées dans testList dans l'ordre depuis le début
            System.out.println(value);
        }
    }
}

La façon de lire l '«instruction étendue pour» dans l'exemple de code ci-dessus est la suivante: «Récupérez les valeurs stockées dans« testList »en tant que valeurs de type« String »dans l'ordre depuis le début et stockez-les dans le nom de variable« value ».» Devenir. La grammaire est similaire pour d'autres langages de haut niveau tels que Python et Ruby, donc si vous êtes déjà familier avec d'autres langages de haut niveau, il ne devrait y avoir aucune difficulté particulière.

Et le résultat de sortie de l'exécution de l'exemple de code ci-dessus est le suivant.

test1
test2
test3

Accès séquentiel à l'aide de la méthode forEach

Avec l'introduction de l'interface fonctionnelle dans JDK1.8, la méthode forEach (Consumer <T>) pour manipuler à plusieurs reprises la collection List a été ajoutée. Cette méthode est très similaire à la méthode forEach (BiConsumer <T, U>) que j'ai introduite plus tôt dans mon article [^ 1] sur l'itération sur des collections de cartes. Il est maintenant possible d'écrire le traitement d'accès séquentiel de manière plus concise et intuitive que l'instruction ʻextended for`.

La méthode d'écriture de base est la suivante.

import java.util.List;
import java.util.ArrayList;

public final class TestForEach {

    public static void main(String[] args) {
        final List<String> testList = new ArrayList<>(3);
        testList.add("test1");
        testList.add("test2");
        testList.add("test3");

        testList.forEach((value) -> {
            //Récupérez les valeurs stockées dans testList dans l'ordre depuis le début
            System.out.println(value);
        });
    }
}

Le point qui semble difficile est l'argument, mais l'argument de la méthode forEach () reçoit une expression lambda qui implémente l'interface fonctionnelle Consumer <T>. Consumer <T> est une interface fonctionnelle qui fait abstraction de l'opération consistant à ne recevoir qu'un seul argument et à ne renvoyer aucune valeur.

J'omettrai l'expression lambda et l'interface fonctionnelle car elles s'écartent de l'objectif de cet article, mais lorsque vous utilisez la méthode forEach () dans List, vous pouvez vous rappeler comment écrire l'exemple de code ci-dessus.

Et le résultat de sortie de l'exécution de l'exemple de code ci-dessus est le suivant.

test1
test2
test3

point important

Comme mentionné précédemment dans l'explication de l'interface fonctionnelle, la méthode forEach ne peut pas renvoyer une valeur en raison des caractéristiques de Consumer <T>. Par conséquent, si vous souhaitez renvoyer «false» en tant que valeur booléenne lorsqu'une erreur est détectée pendant le traitement itératif de List, envisagez d'utiliser l'instruction «extended for».

[^ 1]: [Java] Comment obtenir la clé et la valeur stockées dans Map par traitement itératif

Recommended Posts

[Java] Différentes méthodes pour acquérir la valeur stockée dans List par traitement itératif
[Java] Comment obtenir la clé et la valeur stockées dans Map par traitement itératif
Comment connecter les chaînes de la liste séparées par des virgules
Comment incrémenter la valeur de Map sur une ligne en Java
[Java] Comment rechercher des valeurs dans un tableau (ou une liste) avec la méthode contains
Structure de l'application Web par Java et flux de traitement dans la couche de présentation
Référence Java à comprendre dans la figure
[Traitement × Java] Comment utiliser la boucle
Remplacez List <Optional <T >> par Optional <List <T >> en Java
[Petite histoire Java] Surveiller lorsqu'une valeur est ajoutée à la liste
[Traitement × Java] Comment utiliser la classe
Comment obtenir la date avec Java
[Traitement × Java] Comment utiliser la fonction
Comment créer votre propre annotation en Java et obtenir la valeur
[Note] Java: vitesse de traitement de la liste par objectif
[Java] Jugement en saisissant des caractères dans le terminal
Je veux obtenir la valeur en Ruby
traitement itératif java
Comment enregistrer des fichiers avec l'extension spécifiée sous le répertoire spécifié en Java dans la liste
[Introduction à Java] Liste des choses qui ont été capturées par le 14e jour de programmation
# 1_JAVA Je veux obtenir le numéro d'index en spécifiant un caractère dans la chaîne de caractères
[Java] Comment afficher les jours acquis par LocalDate et DateTimeformatter en japonais
Analyse statistique simple du montant monétaire à partir de la liste recherchée par le développement Mercari Java
Traitement des listes à comprendre avec des images - java8 stream / javaslang-
[Java] Comment omettre le constructeur privé dans Lombok
Exemple de code pour convertir List en List <String> dans Java Stream
[Java] Comment obtenir la valeur maximale de HashMap
Source utilisée pour obtenir l'URL de la source de redirection en Java
Classes et instances Java comprises dans la figure
J'ai essayé d'implémenter la méthode de division mutuelle d'Eugrid en Java
Filtrez la liste facultative Java n ° 2 utile en entreprise et obtenez la première valeur
Utilisez JLine lorsque vous souhaitez gérer les frappes sur la console caractère par caractère en Java
Traitement de branche avec la valeur de retour de RestTemplate et le code d'état de ResponseEntity dans Spring Boot
Divers threads en java
Java aléatoire, divers traitements
Comment obtenir le nom d'une classe / méthode exécutée en Java
Utilisez collection_select pour extraire les données stockées dans Active_Hash
[Java, stream] Trier la liste d'objets en japonais par nom de propriété
ArrayList Afficher tout dans Iterator par traitement itératif en étant dans le tableau
Un moyen simple de vérifier la liste des méthodes / champs dans Java REPL
[Android, Java] Méthode pratique pour calculer la différence en jours
Comment récupérer la valeur de hachage dans un tableau dans Ruby
Créer une méthode pour renvoyer le taux de taxe en Java
Traitement des listes à comprendre avec des images --java8 stream / javaslang --bonus
Plusieurs façons de concaténer des chaînes séparées par des virgules en Java
[Rails] Comment afficher une liste de messages par catégorie
Pensez aux différences entre les fonctions et les méthodes (en Java)
Comment dériver le dernier jour du mois en Java
Comment changer Java à l'ère d'OpenJDK sur Mac
[Rails] Comment afficher les informations stockées dans la base de données dans la vue
Je souhaite simplifier l'instruction if-else de la branche conditionnelle en Java
[Java] Je veux vérifier que les éléments de la liste sont nuls ou vides [Collection Utils]
Comment changer les arguments dans la méthode [Java] (pour ceux qui sont confus en passant par valeur, passant par référence, passant par référence)