[JAVA] ArrayList et le rôle de l'interface vu depuis List

Je suis un nouvel ingénieur diplômé dans une certaine société Web. Je développe principalement Android au quotidien.

Le début de l'affaire en premier lieu

L'autre jour, M. Mentor s'est précipité dans le code Java suivant (Android).

ArrayList<Hoge> hoges = new ArrayList<>();

Mentor "Pourquoi les hoges sont-ils déclarés dans ArrayList? Pourquoi ne pas en faire la liste?"

Lorsqu'on m'a demandé, je n'ai pas pu répondre.

Un ArrayList est requis pour stocker plusieurs instances Hoge et il est naturel que la variable qui contient l'ArrayList soit déclarée dans ArrayList. .. ..

Cependant, après avoir reçu l'explication, j'ai été convaincu par moi-même, alors je voudrais la résumer pour ma propre compréhension.

List et ArrayList

Tout d'abord, je vais résumer la relation entre List et ArrayList.

List La liste est une interface. L'interface est un ensemble de spécifications pour le type de méthode d'une classe, et la liste est une spécification pour le type de méthode requis pour réaliser une collection.

Regarder le contenu de la source (extrait de quelques méthodes seulement)

public interface List<E> extends Collection<E> {
    int size();
    boolean isEmpty();
    boolean contains(Object o);
    Iterator<E> iterator();
    boolean add(E e);
    boolean remove(Object o);
    boolean equals(Object o);
・
・
・
            etc...

Et ainsi de suite, les méthodes sans logique sont rassemblées.

ArrayList ArrayList est un extrait de la source (uniquement celle correspondant à la méthode de List ci-dessus)

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
       public int size() {
            if (ArrayList.this.modCount != this.modCount)
                throw new ConcurrentModificationException();
            return this.size;
       }

       public boolean isEmpty() {
            return size == 0;
       }

       public boolean contains(Object o) {
            return indexOf(o) >= 0;
       }

       public Iterator<E> iterator() {
            return listIterator();
       }

       public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
       }

       public boolean remove(Object o) {
            if (o == null) {
                for (int index = 0; index < size; index++)
                    if (elementData[index] == null) {
                        fastRemove(index);
                        return true;
                    }
            } else {
                for (int index = 0; index < size; index++)
                    if (o.equals(elementData[index])) {
                        fastRemove(index);
                        return true;
                    }
                }
            }
            return false;
       }

       public boolean contains(Object o) {
            return indexOf(o) >= 0;
       }

・
・
・
                   etc...

Comme vous pouvez le voir, dans la classe qui implémente l'interface List, le processus est décrit dans la méthode qui n'était pas contenue dans List. De plus, comme vous pouvez le voir après les implémentations, ArrayList a diverses autres méthodes car il implémente RandomAccess, Cloneable, java.io.Serializable ainsi que List.

À propos, il existe de nombreuses classes qui implémentent List, telles que Stack, Vector et LinkedList, en plus de ArrayList. ArrayList est l'une des classes qui implémente les méthodes définies par List.

Qu'est-ce qui vous satisfait de l'interface?

L'histoire est un peu déviée, mais quel est l'avantage d'implémenter le traitement réel du côté de la classe d'implémentation car les spécifications de la méthode sont résumées?

Le fait est que l'appelant de la classe n'a pas besoin de connaître le contenu de l'implémentation. Par exemple, si vous disposez de l'interface suivante:

public interface FileReader {
    void open();
    void close();
    void read();
}

Supposons que CSVFileReader et JSONFileReader implémentent ce FileReader.

public class CSVFileReader {

    public void open() {
Traitement pour ouvrir correctement le csv
    }

    public void close() {
Traitement qui ferme bien le csv
    }

    public void read() {
Traitement qui lit bien le csv
    }

}
public class JSONFileReader {

    public void open() {
Traitement pour ouvrir JSON joliment
    }

    public void close() {
Traitement qui ferme bien JSON
    }

    public void read() {
Traitement qui lit bien JSON
    }

}

Supposons que vous ayez une méthode qui prend ces classes comme arguments et compte le nombre de caractères dans le fichier.

public int getCount(FileReader fileReader) {
    int count = 0;
    while(true) {
        fileReader.read();
        //Supposons qu'il y ait une logique ici pour sortir de la boucle lorsque la condition de fin est remplie
        count++;
    }
    return count; 
}

L'interface définit uniquement la méthode et ne peut pas être instanciée telle quelle. Cependant, vous pouvez le déclarer comme type.

En d'autres termes, quelle que soit l'implémentation de read (), vous pouvez utiliser une classe qui implémente FileReader tant que vous connaissez l'appelant read (). L'appelant n'a pas besoin de savoir si le contenu à lire est CSV ou JSON.

De cette manière, le mécanisme qui unifie la logique d'appel, c'est-à-dire crée une routine principale commune, est appelé polymorphisme.

Pourquoi déclarer avec ce type?

J'ai résumé la relation entre List et ArrayList

Plus tôt

ArrayList<Hoge> hoges = new ArrayList<>();

Réfléchissez à la façon d'écrire.

Selon l'idée du polymorphisme,

List<Hoge> hoges = new ArrayList<>();

Peut être écrit.

ArrayList, méthode

boolean add(E e);
boolean remove(Object o);
boolean equals(Object o);

Etc. sont définis dans List comme des interfaces et les implémentent. Par exemple

List<Hoge> hoges = new LinkedList<>();

Et même si vous stockez une instance de LinkedList dans hoges

hoges.add(hoge);

Vous pouvez appeler la même méthode comme ceci. Comme je l'ai expliqué plus tôt dans les avantages de l'interface, Si vous avez une méthode qui prend une List comme argument, vous pouvez la recevoir dans ArrayList, LinkedList ou Stack, ce qui vous donne plus de flexibilité.

bien sûr,

ArrayList<Hoge> hoges = new ArrayList<>();

Cela ne veut pas dire que l'écriture est totalement inutile. Bien sûr, ArrayList implémente également RandomAccess, Cloneable, java.io.Serializable, et si vous devez utiliser les méthodes qui y sont définies, vous devez les déclarer dans ArrayList.

Autrement

List<Hoge> hoges = new ArrayList<>();

Il vaudrait mieux écrire.

Résumé

Si vous recherchez par List et ArrayList,

List<Hoge> hoges = new ArrayList<>();

Je peux trouver un article disant que c'est mieux, Je pense que l’important ici n’est pas de tout mémoriser, mais d’expliquer pourquoi vous faites cette déclaration.

Donc, cette fois, j'ai utilisé List et ArrayList comme exemples, et j'ai résumé les raisons pour lesquelles je le fais.

Je pense qu'il y a encore beaucoup de choses étranges dans l'étude de Java. Tsukkomi, nous sommes impatients de vous entendre.

référence

Bases de Java qui peuvent être comprises en 3 minutes] J'ai essayé de résumer les différences entre List et ArrayList http://www.sejuku.net/blog/14886

Différence entre Java, List et ArrayList. http://piyopiyocs.blog115.fc2.com/blog-entry-219.html

List(JavaPlatform SE 7) http://docs.oracle.com/javase/jp/7/api/java/util/List.html

Qu'est-ce qu'une interface? -Le rôle est différent de l'héritage- | Passons en revue la programmation orientée objet (POO) (3) https://www.gixo.jp/blog/5159/

Akira Hirasawa Pourquoi le rendre orienté objet 2e édition Nikkei BP

Recommended Posts

ArrayList et le rôle de l'interface vu depuis List
[Java] Contenu de l'interface de collection et de l'interface de liste
Langage Java du point de vue de Kotlin et C #
Extraire un élément spécifique de la liste des objets
Différence entre List et ArrayList
Les débutants en Java ont brièvement résumé le comportement de Array et ArrayList
Agréger le nombre de personnes tous les 10 ans à partir de la liste <Personne>
[Java] J'ai réfléchi aux mérites et aux utilisations de "interface"
[Java] Supprimer les éléments de la liste
Extraire efficacement plusieurs éléments de la liste de manière aléatoire et sans duplication
J'ai lu la source de ArrayList que j'ai lu
Ceci et cela de JDK
À propos du rôle de la méthode initialize
À propos de removeAll et de retentionAll de ArrayList
De Java naissant (3 ans) à Node.js (4 ans). Et l'impression de retourner à Java
Confirmation et refactoring du flux de la requête au contrôleur dans [httpclient]
[Introduction à Ruby] À propos du rôle de true et break in the while statement
Comparaison des types sûrs à tolérance nulle, à tolérance nulle et à tolérance nulle du point de vue de la sécurité nulle
J'ai essayé de traduire la grammaire de R et Java [Mis à jour de temps en temps]
Importance de l'interface apprise de la collection Java
[Challenge CircleCI from 0] Apprenez les bases de CircleCI
Pliage et dépliage du contenu de la vue Recycleur
À propos du fonctionnement de next () et nextLine ()
[Challenge Docker from 0] Présentation et conditions de Docker
L'histoire de RxJava souffrant de NoSuchElementException
Trouvez l'âge moyen dans la liste <Personne>.
[Java / Swift] Comparaison de l'interface Java et du protocole Swift
Comment trier une liste de SelectItems
Utilisation correcte de l'interface et de la classe abstraite
[Java 7] Divisez la liste Java et exécutez le processus
Trouvez la différence à partir d'un multiple de 10
Vérifiez le fonctionnement de l'interface à travers le thread
Sortie de la somme de chaque nom et de son contenu à partir du tableau multiple
Je veux obtenir récursivement la superclasse et l'interface d'une certaine classe
[N ° 004] Correction de l'écran de la liste des commandes du client
Le contenu de useBodyEncodingForURI a-t-il changé par rapport à Tomcat8?
Vérifiez la version de JDK installée et la version de JDK activée
Pensez à la combinaison de Servlet et Ajax
Comparez la vitesse de l'instruction for et de l'instruction for étendue.
[Java] La partie déroutante de String et StringBuilder
J'ai comparé les caractéristiques de Java et .NET
Apprenez le mécanisme rudimentaire et l'utilisation de Gradle 4.4
À propos de next () et nextLine () de la classe Scanner
Quels sont les avantages de DI et de Thymeleaf?
Extrait la valeur de HashMap et renvoie le résultat trié par valeur de valeur sous forme de liste.
Analyse statistique simple du montant monétaire à partir de la liste recherchée par le développement Mercari Java
Diviser en nombres arbitraires à partir de la latitude et de la longitude du nord, du sud, de l'est et de l'ouest