web-dev-qa-db-fra.com

Comment changer la valeur de l'élément ArrayList dans java

S'il vous plaît aidez-moi avec le code ci-dessous, je reçois la même sortie, même après avoir changé la valeur

import Java.util.*;

class Test {
    public static void main(String[] args) {
        ArrayList<Integer> a = new ArrayList<Integer>();

       // added 0-9 to ArrayList        
          for(int i=0;i<9;i++)
            a.add(new Integer(i));

        // initialize the Iterator
        Iterator<Integer> i = a.iterator();

        // changed the value of first element in List
        if(i.hasNext()) {
            Integer x = i.next();
            x = Integer.valueOf(9);
        }

        // initialized the iterator again and print all the elements
        i = a.iterator();
        while(i.hasNext())
            System.out.print(i.next());
    }
}    

//Output : 012345678

La valeur 9 n'est pas mise à jour.

65
prateeksarda

La liste conserve une référence d'objet à la valeur d'origine stockée dans la liste. Alors, quand vous exécutez cette ligne:

Integer x = i.next();

x et la liste stockent tous deux une référence au même objet. Cependant, lorsque vous exécutez:

x = Integer.valueOf(9);

rien n'a changé dans la liste, mais x enregistre maintenant une référence à un autre objet. La liste n'a pas changé. Vous devez utiliser certaines méthodes de manipulation de liste, telles que

list.set(index, Integer.valueof(9))

Remarque: cela n'a rien à voir avec l'immuabilité de Integer, comme le suggèrent d'autres. Ceci est simplement le comportement de référence d'objet Java de base.


Voici un exemple complet, pour aider à expliquer le point. Notez que cela utilise la classe ListIterator , qui prend en charge la suppression/la configuration d'éléments à mi-itération:

import Java.util.*;

public class ListExample {

  public static void main(String[] args) {

    List<Foo> fooList = new ArrayList<Foo>();
    for (int i = 0; i < 9; i++)
      fooList.add(new Foo(i, i));

    // Standard iterator sufficient for altering elements
    Iterator<Foo> iterator = fooList.iterator();

    if (iterator.hasNext()) {
      Foo foo = iterator.next();
      foo.x = 99;
      foo.y = 42;
    }

    printList(fooList);    

    // List iterator needed for replacing elements
    ListIterator<Foo> listIterator = fooList.listIterator();

    if (listIterator.hasNext()) {
      // Need to call next, before set.
      listIterator.next();
      // Replace item returned from next()
      listIterator.set(new Foo(99,99));
    }

    printList(fooList);
  }

  private static void printList(List<?> list) {
    Iterator<?> iterator = list.iterator();
    while (iterator.hasNext()) {
      System.out.print(iterator.next());
    }
    System.out.println();
  }

  private static class Foo {
    int x;
    int y;

    Foo(int x, int y) {
      this.x = x;
      this.y = y;
    }

    @Override
    public String toString() {
      return String.format("[%d, %d]", x, y);
    }
  }
}

Cela va imprimer:

[99, 42][1, 1][2, 2][3, 3][4, 4][5, 5][6, 6][7, 7][8, 8]
[99, 99][1, 1][2, 2][3, 3][4, 4][5, 5][6, 6][7, 7][8, 8]
87
Duncan Jones

Utilisez la méthode set pour remplacer l'ancienne valeur par une nouvelle.

list.set( 2, "New" );
13
pankaj

Où vous dites que vous changez la valeur du premier élément;

x = Integer.valueOf(9);

Vous changez x pour indiquer un tout nouvel Entier, mais vous ne l'utilisez plus jamais. Vous ne changez pas la collection en aucune façon.

Puisque vous travaillez avec ArrayList, vous pouvez utiliser ListIterator si vous voulez un itérateur qui vous permette de changer les éléments, ceci est l'extrait de votre code cela devrait être changé;

// initialise l'itérateur
ListIterator <entier> i = a .listIterator ();

// a changé la valeur de l'élément frist dans la liste
if (i.hasNext ()) {
I.next ();
i.set (Integer.valueOf (9));) // Change l'élément où se trouve actuellement l'itérateur
}

// Nouvel itérateur, et affiche tous les éléments
Itérateur iter = a.iterator ();
while (iter.hasNext ())
System.out.print (iter.next ());

>> 912345678

Malheureusement, la même chose ne peut pas être étendue à d'autres collections comme Set <T>. Les détails d'implémentation (un hachage, par exemple implémenté comme une table de hachage et changer d'objet pourraient changer la valeur de hachage et donc l'ordre des itérations) font de Set <T> un type de structure de données "ajouter/supprimer seulement", et changer le contenu du tout en itérant, ce n’est pas sûr.

11
Joachim Isaksson

Vous essayez de changer la valeur dans la liste, mais vous ne faites que changer la référence de x. Effectuer les modifications suivantes uniquement x, rien dans la collection:

x = Integer.valueOf(9);

De plus, Integer est immuable, ce qui signifie que vous ne pouvez pas modifier la valeur dans l'objet Integer (ce qui nécessiterait de toute façon une méthode différente). Cela signifie que vous devez remplacer l'objet entier. Il n'y a aucun moyen de faire cela avec un Iterator (sans ajouter votre propre couche de boxe). Procédez plutôt comme suit:

a.set(0, 9);
1
CrazyCasta

Je suis d'accord avec Duncan ... Je l'ai essayé avec un objet mutable mais j'obtiens toujours le même problème ... J'ai une solution simple à cela ... utilisez ListIterator à la place d'Iterator et utilisez la méthode set de ListIterator

ListIterator<Integer> i = a.listIterator();
//changed the value of first element in List
Integer x =null;
        if(i.hasNext()) {
            x = i.next();
            x = Integer.valueOf(9);
        }
    //set method sets the recent iterated element in ArrayList
    i.set(x);
        //initialized the iterator again and print all the elements
        i = a.listIterator();
        while(i.hasNext())
        System.out.print(i.next());

Mais cela me contraint à l’utiliser uniquement pour ArrayList, qui peut utiliser ListIterator ... j’aurai le même problème avec n’importe quelle autre collection.

1
prateeksarda

Je pense que le problème est que vous pensez que la déclaration ...

x = Integer.valueOf(9);

... cause que la valeur de '9' soit 'stockée' dans (!) l'Objet sur lequel x fait référence.

Mais c'est faux.

Au lieu de cela, l'instruction provoque quelque chose de similaire, comme si vous appeliez

x = new Integer(9); 

Si vous consultez le code source Java, vous verrez ce qui se passe en détail.

Voici le code de la méthode "valueOf (int i)" dans la classe "Integer":

public static Integer valueOf(int i) {
    assert IntegerCache.high >= 127;
    if (i >= IntegerCache.low && i <= IntegerCache.high)
        return IntegerCache.cache[i + (-IntegerCache.low)];
    return new Integer(i);
}

et en outre, chaque fois que la classe IntegerCache est utilisée pour la première fois, le script suivant est appelé:

static {
        // high value may be configured by property
        int h = 127;
        String integerCacheHighPropValue =
            Sun.misc.VM.getSavedProperty("Java.lang.Integer.IntegerCache.high");
        if (integerCacheHighPropValue != null) {
            int i = parseInt(integerCacheHighPropValue);
            i = Math.max(i, 127);
            // Maximum array size is Integer.MAX_VALUE
            h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
        }
        high = h;

        cache = new Integer[(high - low) + 1];
        int j = low;
        for(int k = 0; k < cache.length; k++)
            cache[k] = new Integer(j++);
    }

Vous voyez qu'un nouvel objet Integer est créé avec "new Integer (i)" dans la méthode valueOf ... ... ou qu'une référence à un objet Integer qui est stocké dans IntegerCache est renvoyée.

Dans les deux cas, x fera référence à un nouvel objet.

Et c’est pourquoi la référence à l’objet de votre liste est perdue lorsque vous appelez ...

x = Integer.valueOf(9);

Au lieu de cela, en combinaison avec une utilisation de ListIterator ...

i.set(Integer.valueOf(9));

... après avoir obtenu l'élément avec lequel vous voulez changer ...

i.next();
1
matthiasboesinger

Changez-le en for(int i=0;i<=9;i++)

0
Mr. RaZz