Come cambiare il valore dell’elemento ArrayList in java

Per favore aiutami con il codice qui sotto, ottengo lo stesso risultato anche dopo aver cambiato il valore

import java.util.*; class Test { public static void main(String[] args) { ArrayList a = new ArrayList(); // added 0-9 to ArrayList for(int i=0;i<9;i++) a.add(new Integer(i)); // initialize the Iterator Iterator 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 

Il valore 9 non si sta aggiornando.

L’elenco mantiene un riferimento a un object al valore originale memorizzato nell’elenco. Quindi quando esegui questa linea:

 Integer x = i.next(); 

Sia x che la lista stanno memorizzando un riferimento allo stesso object. Tuttavia, quando esegui:

 x = Integer.valueOf(9); 

nulla è cambiato nella lista, ma x sta ora memorizzando un riferimento a un object diverso. L’elenco non è cambiato. È necessario utilizzare alcuni dei metodi di manipolazione delle liste, come

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

Nota: questo non ha nulla a che fare con l’immutabilità di Integer , come altri suggeriscono. Questo è solo un comportamento base di riferimento agli oggetti Java.


Ecco un esempio completo, per aiutare a spiegare il punto. Notare che ciò fa uso della class ListIterator , che supporta la rimozione / impostazione degli elementi a metà iterazione:

 import java.util.*; public class ListExample { public static void main(String[] args) { List fooList = new ArrayList(); for (int i = 0; i < 9; i++) fooList.add(new Foo(i, i)); // Standard iterator sufficient for altering elements Iterator 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 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); } } } 

Questo stamperà:

 [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] 

Dove dici che stai cambiando il valore del primo elemento;

 x = Integer.valueOf(9); 

Stai cambiando x per puntare a un intero intero completamente nuovo, ma non lo utilizzerai mai più. Non stai cambiando la collezione in alcun modo.

Dato che stai lavorando con ArrayList, puoi usare ListIterator se vuoi un iteratore che ti permetta di cambiare gli elementi, questo è lo snippet del tuo codice che dovrebbe essere cambiato;

// inizializza l’Iterator
ListIterator i = a. listIterator () ;

// ha cambiato il valore dell’elemento frist in List
if (i.hasNext ()) {
i.next ();
i.set (Integer.valueOf (9)); // Cambia l’elemento al quale l’iteratore è attualmente
}

// Nuovo iteratore e stampa tutti gli elementi
Iterator iter = a.iterator ();
while (iter.hasNext ())
System.out.print (iter.next ());

>> 912345678

Purtroppo lo stesso non può essere esteso ad altre raccolte come Set . Dettagli di implementazione (un HashSet ad esempio implementato come una tabella hash e cambiando l’object potrebbe modificare il valore hash e quindi l’ordine di ripetizione) rende Set un tipo “aggiungi solo / rimuovi solo” di struttura dati e modificando il contenuto affatto mentre iterare su di esso non è sicuro.

Usa il metodo set per sostituire il vecchio valore con uno nuovo.

 list.set( 2, "New" ); 

Stai cercando di cambiare il valore nell’elenco, ma tutto quello che stai facendo è cambiare il riferimento di x. Facendo quanto segue si cambiano solo x, non nulla nella collezione:

 x = Integer.valueOf(9); 

Inoltre, Integer è immutabile, il che significa che non è ansible modificare il valore all’interno dell’object Integer (che richiederebbe comunque un metodo diverso). Ciò significa che è necessario sostituire l’intero object. Non c’è modo di farlo con un Iterator (senza aggiungere il proprio livello di boxe). Fai invece quanto segue:

 a.set(0, 9); 

Sono d’accordo con Duncan … L’ho provato con un object mutevole ma ho ancora lo stesso problema … Ho una soluzione semplice a questo … usare ListIterator invece Iterator e usare il metodo set di ListIterator

 ListIterator 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()); 

Ma questo mi costringe a usare questo solo per ArrayList che può usare ListIterator … Avrò lo stesso problema con qualsiasi altra Collezione

Penso che il problema sia che pensi che la dichiarazione …

 x = Integer.valueOf(9); 

… fa sì che il valore di “9” venga “memorizzato” in (!) l’object su cui fa riferimento x.

Ma questo è sbagliato.

Invece l’affermazione provoca qualcosa di simile, come se tu chiamassi

 x = new Integer(9); 

Se guardi il codice sorgente Java, vedrai cosa succede in dettaglio.

Ecco il codice del metodo “valueOf (int i)” nella class “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); } 

e inoltre, ogni volta che viene utilizzata la class IntegerCache per la prima volta viene richiamato lo script seguente:

 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++); } 

Vedete che o un nuovo Oggetto intero viene creato con "new Integer (i)" nel metodo valueOf ... ... oppure viene restituito un riferimento a un Oggetto intero che è memorizzato in IntegerCache.

In entrambi i casi x farà riferimento a un nuovo object.

Ed è per questo che il riferimento all'Oggetto nel tuo elenco si perde quando chiami ...

 x = Integer.valueOf(9); 

Invece di farlo, in combinazione con ListIterator usa ...

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

... dopo aver ottenuto l'elemento che vuoi cambiare con ...

 i.next(); 

Cambiarlo in for(int i=0;i<=9;i++)