web-dev-qa-db-fra.com

Différence entre Arrays.asList (tableau) et nouvel ArrayList <Integer> (Arrays.asList (tableau))

Quelle est la différence entre 

1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy
2.List<Integer> list2 = Arrays.asList(ia);

ia est un tableau d'entiers.

J'ai appris que certaines opérations ne sont pas autorisées dans list2. pourquoi est-il ainsi? comment est-il stocké en mémoire (références/copie)?

Lorsque je mélange les listes, list1 n'affecte pas le tableau d'origine, mais list2 le fait. Mais toujours list2 est un peu déroutant. 

La différence de ArrayList dans la liste diffère de la création d'une nouvelle ArrayList

list1 differs from (1)
ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));
86
Dineshkumar
  1. Tout d'abord, voyons ce que cela fait:

    Arrays.asList(ia)
    

    Il prend un tableau ia et crée un wrapper qui implémente List<Integer>, ce qui rend le tableau d'origine disponible sous forme de liste. Rien n'est copié et tous, un seul objet wrapper est créé. Les opérations sur le wrapper de liste sont propagées dans le tableau d'origine. Cela signifie que si vous mélangez le wrapper de liste, le tableau d'origine est également mélangé, si vous écrasez un élément, il est écrasé dans le tableau d'origine, etc. Bien sûr, certaines opérations List ne sont pas autorisées sur le wrapper, comme l'ajout ou en supprimant des éléments de la liste, vous pouvez uniquement les lire ou les écraser.

    Notez que le wrapper de liste n’étend pas ArrayList - c’est un type d’objet différent. ArrayLists ont leur propre tableau interne, dans lequel ils stockent leurs éléments et sont capables de redimensionner les tableaux internes, etc. Le wrapper ne possède pas son propre tableau interne, il ne fait que propager des opérations dans le tableau qui lui est attribué.

  2. D'autre part, si vous créez ensuite un nouveau tableau en tant que 

    new ArrayList<Integer>(Arrays.asList(ia))
    

    ensuite, vous créez un nouveau ArrayList, qui est une copie complète et indépendante de l’original. Bien que ici, vous créez le wrapper en utilisant également Arrays.asList, il est utilisé uniquement lors de la construction du nouveau ArrayList et est ensuite récupéré. La structure de cette nouvelle ArrayList est complètement indépendante du tableau d'origine. Il contient les mêmes éléments (le tableau d'origine et cette nouvelle référence ArrayList font référence aux mêmes entiers en mémoire), mais il crée un nouveau tableau interne contenant les références. Ainsi, lorsque vous mélangez, ajoutez, supprimez des éléments, etc., le tableau d'origine reste inchangé.

182
Petr Pudlák

Eh bien, c'est parce que ArrayList résultant de Arrays.asList() n'est pas du type Java.util.ArrayList. Arrays.asList() crée une ArrayList de type Java.util.Arrays$ArrayList qui n’étend pas Java.util.ArrayList mais étend seulement Java.util.AbstractList

19
Chris
List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy

Dans ce cas, list1 est de type ArrayList.

List<Integer> list2 = Arrays.asList(ia);

Ici, la liste est renvoyée sous forme d'une vue List, ce qui signifie qu'elle ne possède que les méthodes attachées à cette interface. Par conséquent, certaines méthodes ne sont pas autorisées sur list2.

ArrayList<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));

Ici, vous créez une nouvelle ArrayList. Vous lui transmettez simplement une valeur dans le constructeur. Ce n'est pas un exemple de casting. En casting, cela pourrait ressembler davantage à ceci:

ArrayList list1 = (ArrayList)Arrays.asList(ia);
8
christopher

Je suis assez en retard ici, de toute façon, j'ai pensé qu'une explication avec des références doc serait préférable pour quelqu'un qui cherche une réponse.

  1. Java.util.Arrays
  • Ceci est une classe d’utilitaires avec un tas de méthodes statiques à utiliser sur un tableau donné
  • asList est une méthode statique de ce type qui prend un tableau en entrée et retourne un objet de Java.util.Arrays.ArrayList, qui est une classe imbriquée statique qui étend AbstractList et qui implémente l'interface List.
  • Donc Arrays.asList (inarray) retourne un wrapper List autour du tableau d’entrée mais ce wrapper est Java.util.Arrays.ArrayList et non Java.util.ArrayList et fait référence au même tableau, ce qui permet d’ajouter plus d’éléments à List. Un tableau encapsulé affecterait également celui-ci et nous ne pouvons pas en changer la longueur.
  1. Java.util.ArrayList
  • ArrayList a un groupe de constructeurs surchargés

    public ArrayList () - // retourne une liste avec une capacité par défaut 10

    public ArrayList (Collection c)

    public ArrayList (int initialCapacity)

  • Ainsi, lorsque nous passons Arrays.asList renvoyé objet, c'est-à-dire List (AbstractList), au deuxième constructeur ci-dessus, il crée un nouveau tableau dynamique (la taille de ce tableau augmente à mesure que nous ajoutons plus d'éléments que sa capacité. De plus, les nouveaux éléments n'affectent pas le tableau d'origine. ) copie superficielle du tableau d'origine ( copie superficielle signifie qu'il copie uniquement sur les références et ne crée pas un nouvel ensemble de mêmes objets que dans le tableau d'origine)

3
John Frusciante

Notez que, dans Java 8, 'ia' ci-dessus doit être Integer [] et non int []. Arrays.asList () d'un tableau int retourne une liste avec un seul élément. Lorsqu’il utilise l’extrait de code d’OP, le compilateur détecte le problème, mais certaines méthodes (par exemple, Collections.shuffle ()) échouent en silence à faire ce que vous attendez.

2
Carl Burke
String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.List<String> namesList = Arrays.asList(names);

ou

String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.List<String> temp = Arrays.asList(names);         

Au-dessus de la déclaration ajoute le wrapper sur le tableau d'entrée. Ainsi, les méthodes telles que add & remove ne seront pas applicables sur l'objet de référence de la liste 'namesList'.

Si vous essayez d'ajouter un élément dans le tableau/la liste existant, vous obtiendrez "Exception dans le fil" principal "Java.lang.UnsupportedOperationException".

L'opération ci-dessus est en lecture seule ou en lecture seule. 
Nous ne pouvons pas effectuer d’ajout ou de suppression d’opération dans un objet de liste . Mais

String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.ArrayList<String> list1 = new ArrayList<>(Arrays.asList(names));

ou

String names[] = new String[]{"Avinash","Amol","John","Peter"};
Java.util.List<String> listObject = Arrays.asList(names);
Java.util.ArrayList<String> list1 = new ArrayList<>(listObject);

Dans l’instruction ci-dessus, vous avez créé une instance concrète d’une classe ArrayList et passé une liste en tant que paramètre.

Dans ce cas, la méthode add & remove fonctionnera correctement car les deux méthodes sont issues de la classe ArrayList. Par conséquent, nous n'obtiendrons aucune exception UnSupportedOperationException.
Les modifications apportées à l'objet Arraylist (méthode permettant d'ajouter ou de supprimer un élément dans/d'un arraylist) ne seront pas reflétées dans l'objet Java.util.List d'origine.

String names[] = new String[] {
    "Avinash",
    "Amol",
    "John",
    "Peter"
};

Java.util.List < String > listObject = Arrays.asList(names);
Java.util.ArrayList < String > list1 = new ArrayList < > (listObject);
for (String string: list1) {
    System.out.print("   " + string);
}
list1.add("Alex"); //Added without any exception
list1.remove("Avinash"); //Added without any exception will not make any changes in original list in this case temp object.


for (String string: list1) {
    System.out.print("   " + string);
}
String existingNames[] = new String[] {
    "Avinash",
    "Amol",
    "John",
    "Peter"
};
Java.util.List < String > namesList = Arrays.asList(names);
namesList.add("Bob"); // UnsupportedOperationException occur
namesList.remove("Avinash"); //UnsupportedOperationException
2
Avinash Pande

Beaucoup de gens ont déjà répondu aux détails mécaniques, mais il convient de noter: Ceci est un choix de conception médiocre, par Java.

La méthode asList de Java est documentée sous la forme "Retourne une taille fixe liste ...". Si vous prenez son résultat et appelez (par exemple) la méthode .add, il jette un UnsupportedOperationException. C'est un comportement non intuitif! Si une méthode dit qu'elle renvoie List, l'attente standard est qu'elle renvoie un objet prenant en charge les méthodes de l'interface List. Un développeur ne devrait pas avoir à mémoriser which des nombreuses méthodes util.List et créer des List qui ne prennent pas en charge toutes les méthodes List.

S'ils avaient nommé la méthode asImmutableList, cela aurait du sens. Ou bien, si la méthode retournait simplement un List (et copiait le tableau de sauvegarde), cela aurait du sens. Ils ont décidé de privilégier les noms abrégés et performances d'exécution, au détriment de la violation du principe de moindre surprise et du code OO. pratique d'éviter UnsupportedOperationExceptions.

(En outre, les concepteurs ont peut-être créé un interface ImmutableList afin d'éviter une multitude de UnsupportedOperationExceptions.)

1
not-just-yeti
package com.copy;

import Java.util.ArrayList;
import Java.util.Arrays;
import Java.util.Iterator;
import Java.util.List;

public class CopyArray {

    public static void main(String[] args) {
        List<Integer> list1, list2 = null;
        Integer[] intarr = { 3, 4, 2, 1 };
        list1 = new ArrayList<Integer>(Arrays.asList(intarr));
        list1.add(30);
        list2 = Arrays.asList(intarr);
        // list2.add(40); Here, we can't modify the existing list,because it's a wrapper
        System.out.println("List1");
        Iterator<Integer> itr1 = list1.iterator();
        while (itr1.hasNext()) {
            System.out.println(itr1.next());
        }
        System.out.println("List2");
        Iterator<Integer> itr2 = list2.iterator();
        while (itr2.hasNext()) {
            System.out.println(itr2.next());
        }
    }
}
1
VicXj

Résumé de la différence -

lorsque la liste est créée sans utiliser de nouvel opérateur, la méthode Arrays.asList () renvoie le wrapper qui signifie 

1. vous pouvez effectuer une opération d'ajout/mise à jour.

2. les modifications effectuées dans le tableau d'origine seront également répercutées sur Liste et vice versa.

0
Raj

En réponse à certains commentaires posant des questions sur le comportement de Arrays.asList () depuis Java 8:

    int[] arr1 = {1,2,3};
    /* 
       Arrays are objects in Java, internally int[] will be represented by 
       an Integer Array object which when printed on console shall output
       a pattern such as 
       [I@address for 1-dim int array,
       [[I@address for 2-dim int array, 
       [[F@address for 2-dim float array etc. 
   */
    System.out.println(Arrays.asList(arr1)); 

    /* 
       The line below results in Compile time error as Arrays.asList(int[] array)
       returns List<int[]>. The returned list contains only one element 
       and that is the int[] {1,2,3} 
    */
    // List<Integer> list1 = Arrays.asList(arr1);

    /* 
       Arrays.asList(arr1) is  Arrays$ArrayList object whose only element is int[] array
       so the line below prints [[I@...], where [I@... is the array object.
    */
    System.out.println(Arrays.asList(arr1)); 

    /* 
     This prints [I@..., the actual array object stored as single element 
     in the Arrays$ArrayList object. 
    */
    System.out.println(Arrays.asList(arr1).get(0));

    // prints the contents of array [1,2,3]
    System.out.println(Arrays.toString(Arrays.asList(arr1).get(0)));

    Integer[] arr2 = {1,2,3};
    /* 
     Arrays.asList(arr) is  Arrays$ArrayList object which is 
     a wrapper list object containing three elements 1,2,3.
     Technically, it is pointing to the original Integer[] array 
    */
    List<Integer> list2 = Arrays.asList(arr2);

    // prints the contents of list [1,2,3]
    System.out.println(list2);
0
NINCOMPOOP
1.List<Integer> list1 = new ArrayList<Integer>(Arrays.asList(ia));  //copy
2.List<Integer> list2 = Arrays.asList(ia);

Dans la ligne 2, Arrays.asList(ia) renvoie une référence List d'objet de classe interne défini dans Arrays, également appelé ArrayList mais qui est privé et étend uniquement AbstractList. Cela signifie que ce qui est retourné de Arrays.asList(ia) est un objet de classe différent de ce que vous obtenez de new ArrayList<Integer>.

Vous ne pouvez pas utiliser certaines opérations sur la ligne 2 car la classe privée interne dans Arrays ne fournit pas ces méthodes.

Jetez un coup d’œil à ce lien et voyez ce que vous pouvez faire avec la classe interne privée: http://grepcode.com/file/repository.grepcode.com/Java/root/jdk/openjdk/6-b14 /Java/util/Arrays.Java#Arrays.ArrayList

La ligne 1 crée un nouvel objet ArrayList en copiant des éléments à partir de ce que vous obtenez à la ligne 2. Vous pouvez donc faire ce que vous voulez, car Java.util.ArrayList fournit toutes ces méthodes.

0
zek_w