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.
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]
Utilisez la méthode set pour remplacer l'ancienne valeur par une nouvelle.
list.set( 2, "New" );
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.
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);
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.
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();
Changez-le en for(int i=0;i<=9;i++)