Newsgroup: it.comp.java
Titolo: Copiare un ArrayList

Ciao a tutti.
Come posso fare a copiare un ArrayList in un altro ArrayList per 
valore e non per riferimento?
Grazie.
--  
Postato da Virgilio Newsgroup 
http://newsgroup.virgilio.it
Completo come il newsreader, ma senza il newsreader

 valore e non per riferimento?
Puoi usare il costruttore di ArrayList così :
ArrayList nuovo = new ArrayList (vecchio);
Oppure puoi clonare un ArrayList (puoi farlo visto che implementa
l'interfaccia Clonable) :
// Dovrebbe andare ma non ho provato, meglio usare il costruttore mi sa
ArrayList nuovo = (ArrayList) vecchio.clone();
-- 
ay containin
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Xoen
Jabber ID : 
xo...@jabber.linux.it
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Non esiste la copia per valore in giava. Al limite copi per valore il
riferimento.
Quindi immagino che la strada sia copiare l'ArrayList in un nuovo
ArrayList...
Cia'
   F

Grazie
Francesco Galli ha scritto:



 Non esiste la copia per valore in giava.
Non conosco giava.
Stiamo passando di passaggio di parametri a metodi?
Se si allora il tipo di passaggio dipende dal tipo di parametri che si
passa al metodo, e cioč, se si passa un parametro int, char, float, etc
(i tipi primitivi insomma) il passaggio viene fatto per valore (cioč si
passa al metodo una copia del valore), altrimenti se si passa al metodo
un'oggetto viene passato al metodo un riferimento all'oggetto originale
(cioč solo il "puntatore" all'oggetto) questo per risparmiare tempo, e
migliorare le prestazioni.
Quindi, se si passa un tipo primitivo ad un metodo, eventuali modifiche
non si riperquoteranno all'esterno del metodo.
Se invece si passa un'oggetto le eventuali modifiche all'interno del
metodo saranno fatte direttamente all'oggetto passato.
-- 


 metodo saranno fatte direttamente all'oggetto passato.
allora di java non c'ho capito niente....
http://www.wmlscript.it/java/corso_14.asp
ero proprio convinto che il passaggio fosse sempre e inequivocabilmente
effettuato per valore....

Il problema e' che in Giava non esiste niente di diverso dagli oggetti... di
cui passi i puntatori... per valore.
Ovvio che passare i puntatori per valore non e' molto diverso dal passaggio
per riferimento.
(che senno' voglio ridere a passare oggetti grossi per valore. sisisi.
voglio ridere, a definire costruttori di copia espliciti o impliciti).
Francesco

 voglio ridere, a definire costruttori di copia espliciti o impliciti).
LOL, appunto, che poi a pensarci non è poi così complicato da capire,
alla fine si tratta sempre di passaggio per valore, solo che il
significato cambia se si tratta in un tipo primitivo o di un'oggetto.


 }
SBAGLIATO... basta scrivere 2 righe di codice per verificarlo.
la confusione deriva dal fatto che in Java l'assegnazione (e NON il
passaggio di oggetti a sottoprogrammi), avviene nel seguente modo:
se assegno una variabile di tipo primitivo ad un'altra il valore verra'
copiato. es:
int a=1;
int b=a;
b=b+1;
a questo punto a vale 1 e b vale 2.
se invece si tratta di oggetti non primitivi la cosa e' diversa, inquanto
l'operatore = effettua una copia del rifrimento all'oggetto, e non
dell'oggetto in se per se.
MyObject a=new  MObject ();
MyObject b=a;
a.cambiaQualcosa();
a questo punto il cambiamento effettuato su a si riperquote anche su b.
Spero di essere stato chiaro.
Ciao
Claudio

 Spero di essere stato chiaro.
Si :) Comunque ho l'impressione che stiamo dicendo tutti la stessa cosa ;)


 il massimo come  performance, ma e' cosi.
   No, non viene copiato alcun oggetto in memoria. L'oggetto nello heap e'
uno, e' il suo puntatore (=il puntatore all'oggetto) che viene passato per
valore. Quindi ogni modifica all'ambiente del chiamato si ripercuote per
effetto collaterale sull'ambiente del chiamante, ma non viene effettuata
alcuna copia... difatti in Java il concetto di "costruttore di copia" non
esiste, mentre (ad esempio) in C++ si.
Ciao,
   francesco

pensate pure quello che vi pare, ma il Java non e' un'opinione.....
e ribadisco, date un'occhiata a questo articolo che spiega molto bene:
http://www.wmlscript.it/java/corso_14.asp
intanto fatevi questa prova:
public class Prova {
    public static void main(String args[]) {
        String prova="cane";
        MyObject o= new MyObject();
        o.setString(prova);
        o.setString("gatto");
        System.out.println(prova);
        System.out.println(o.getString());
    }
}
public class MyObject {
    private  String myString;
    public void setString(String s){
        myString=s;
    }
    public String getString(){
        return myString;
    }
}
quale credete sia l'output? secondo il vostro ragionamento dovrebbe essere
gatto
gatto
invece a me risulta
cane
gatto
con questo passo e chiudo
ciao
Claudio

 Si :) Comunque ho l'impressione che stiamo dicendo tutti la stessa cosa ;)
io credo di no
ciao
Claudio

 esiste, mentre (ad esempio) in C++ si.
provati l'esempio che ho appena postato nel post successivo e verifica
ciao
Claudio

 gatto
Giustissimo!
Ma cosa hai dimostrato? Nulla (non mi fraintendere)
Nella classe MyObject non modifichi l'oggetto String semplicemente
quando richiami il metodo setString della classe MyObject assegni al
campo myString un _ALTRO_ oggetto string.
1) String prova = "cane";
// Crei un'oggetto String che contiene la stringa "cane"
2) o.setString (prova);
// Dopo questo il campo myString di o (oggetto MyObject) punterà
all'oggetto String prova.
3) o.setString ("gatto");
// Dopo questo il campo myString di o (oggetto MyObject) punterà
all'oggetto String "gatto", e non più all'oggetto String prova.
4) System.out.println (prova);
// Visualizza l'oggetto String prova, e cioè "cane"
5) System.out.println (o.getString());
// Il metodo getString restituisce un riferimento ad un oggetto di tipo
// String, un riferimento al campo privato myString di o (un'oggetto di
// tipo MyObject), il campo myString punterà all'oggetto String "gatto"
(istruzione al punto 3) e quindi verrà visualizzato "gatto".
PS: Non hai dimostrato nulla, per la cronaca sono più di due righe, e
sono sempre più convinto che stiamo dicendo tutti (ancora) la stessa cosa ;)


 > }
ma secondo il vostro ragionamento in quel o.setString(prova); sto passando
il puntatore alla variabile prova.
Cosa facilmente smentita delle 3 righe successive

 con questo passo e chiudo
Prova questo ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import java.util.*;
public class Prova {
    public static void main(String args[]) {
	ArrayList lista = new ArrayList ();
	lista.add (new Integer (5));
        System.out.println (lista);
	modifico (lista);
        System.out.println (lista);		
    }
	static void modifico (List lista) {
		lista.add ("Passo e chiudo...");
	}
 
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Quale pensi sia l'output del programma (più o meno)?
[5]
[5]
?! O
[5]
[5, Passo e chiudo...]
Dici che ho qualche problema alla VM :) ?


 il puntatore alla variabile prova.
/**************
*   OGGETTI   *
***************/
Variabili                 Memoria
prova           --->     "Ciao"
// var2 = prova
Variabili                 Memoria
prova = var2       --->     "Ciao"
/*********************
*   TIPI PRIMITIVI   *
**********************/
Variabili                 Memoria
prova           --->        10
// var2 = prova
Variabili                 Memoria
prova        --->     10
var2         --->     10
// var2 = 17
Variabili                 Memoria
prova        --->     10
var2         --->     17
// prova = 899
Variabili                 Memoria
prova        --->     899
var2         --->     17
PS :Spero di essere stato chiaro.


> Dici che ho qualche problema alla VM :) ?
lascia fare le liste... che magari un giorno te le spiego... :))))
prova con un esempino ancora piu' semplice:
public class Prova {
    public static void main(String args[]) {
        String myString = "ciao";
        System.out.println(myString);
        modifico(myString);
        System.out.println(myString);
    }
    static void modifico(String s) {
        s = s + " Passo e chiudo...";
    }
}
L'output (provare per credere) e':
ciao
ciao
Claudio

 
http://www.wmlscript.it/java/corso_14.asp
Gli ho dato un'occhiata ...
Cito la tua fonte :
La differenza pratica tra un reference ed una variabile, è evidente
nelle assegnazioni. Consideriamo il seguente frammento di codice:
double unNumero = 5.0;
double unAltroNumero = unNumero;
Data unGiorno = new Data();
Data unAltroGiorno = unGiorno;
Sia per il tipo di dato primitivo, sia per quello complesso, abbiamo
quindi creato un comportamento equivalente: dichiarazione ed
assegnazione di un valore, e riassegnazione di un altro valore.
La variabile unAltroNumero, assumerà lo stesso valore della variabile
unNumero, ma le due variabili, rimarranno indipendenti l’una dall’altra.
Infatti, il valore della variabile unNumero, sarà copiato nella
variabile unAltroNumero. Se il valore di una delle due variabili sarà in
seguito modificato, l’altra variabile non apporterà modifiche al proprio
valore.
Invece, il reference unAltroGiorno, semplicemente assumerà il valore
(cioè l’indirizzo) del reference unGiorno. Ciò significa che
unAltroGiorno punterà allo stesso oggetto cui punta unGiorno.
Quindi, se in seguito sarà apportata una qualche modifica tramite uno
dei due reference all’oggetto comune, ovviamente questa sarà
verificabile anche tramite l’altro reference. Per intenderci:
unGiorno.anno
è sicuramente equivalente a:
unAltroGiorno.anno
** Passaggio di parametri per valore **
Il passaggio di parametri in Java avviene sempre per valore.
Stesso discorso vale per i tipi reference: viene sempre passato il
valore del reference, ovvero, l'indirizzo in memoria
Il fatto che il passaggio avvenga sempre per valore, garantisce che un
oggetto possa essere modificato, e contemporaneamente, si è certi che
dopo la chiamata del metodo il reference punti sempre allo stesso oggetto.
*** FINE ***
Dice cose giuste questo articolo.
Tutto è passato per valore, solo che se passi un oggetto il valore che
si passa è il puntatore all'oggetto (detto reference), e quindi è come
se si passasse per indirizzo.


 ciao
Ancora una volta...il metodo modifico (String s) sebbene si chiami
modifico non modifica un bel null (non è un'errore di battitura :) ) ...
Fai la stessa prova con un oggetto StringBuffer, e dentro modifico
chiama s.append (" Passo e non chiudo tanto è inutile ;) ...");
Facci sapere com'è l'output, fai la prova tu che a me abbutta :)
PS: abbutta = stufa


 se si passasse per indirizzo.
esatto, come nel caso delle liste, ma ti sei accorto da dove e' nata la
disussione?
cito un tuo post delle ore 15:42:



Aspetta aspetta...diciamo che la scelta di String è stata sfortunata
(visto che in java non sono modificabili per questioni di prestazioni),
ma con "modificando s dentro metodo sarà modificato anche l'oggetto
puntato da msg fuori" volevo dire che se s è instanza di una classe
allora modificandola all'interno di metodo sarà modificato anche
all'esterno. Non che assegnando ad s un'altro oggetto String
automaticamente anche msg fuori da metodo() punterà all'altro oggetto
String.
Fate finta che il prototipo di metodo sia metodo (StringBuffer s).
(Alla fine, come avevo detto, mi sa che stiamo dicendo le stesse cose)
Altro esempio :
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
public class Prova {
    public static void main(String args[]) {
	MyObject o = new MyObject (5);
	System.out.println (o);
	modifico (o);
	System.out.println (o);
    }
    static void modifico (MyObject parametro) {
	parametro.setI (899);
    }
 
}
class MyObject {
	int i;
	MyObject (int i) {
		this.i = i;
	}
	void setI (int i) {
		this.i = i;
	}
	int getI () {
		return i;
	}
	public String toString () {
		return ""+i;
	}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


ok, ci siamo arrivati.... :))))
non so te, ma io vado a cena....
ciao
Claudio

 Claudio
Piacere, Xoen.


 
mi pare che il nodo della questione sia l'operatore =
che sembra una cazzata, ma in buona parte dei linguaggi procedurali
vuol dire una cosa ben diversa.
ciao.

 Cosa facilmente smentita delle 3 righe successive
   io spero che di mestiere tu non faccia il programmatore Java, e neanche
il programmatore, senno' e' un casino.
Allora, provo a spiegartelo in parole semplici visto che... no... non ci
riesco...
MAREMMA TROGOLA!
Allora. In Java le modifiche fatte nel chiamato si ripercuotono
nell'ambiente del chiamante. Questo e' un assioma. E' il linguaggio che e'
fatto cosi'.
Non ti seri reso conto che "prova" non e' a sinistra di alcun assegnamento?
Diverso sarebbe stato se MyObject.setString(String) fosse stato:
myString = s;
s = "ora si, che lo cambio!";
In quel caso... fallo girare...
Ora, io posso capire che alle volte manchino le basi di gestione heap e
stack, ma porco cane, stabilire cosa e' a sinistra di un operatore e cosa
no...

In Java l'unico passaggio consentito è per valore.
Se la variabile è primitiva viene copiato il valore,
se la variabile è di tipo riferimento, anche qui viene copiato il valore,
che in questo caso è l'indirizzo di memoria dove risiede l'oggetto.
Questo è diverso dal dire che c'è il passaggio per riferimento, infatti
nel metodo chiamato la variabile in cui viene copiato l'indirizzo è
diversa dalla variabile originale. Se si assegna questa variabile a
qualcos'altro non viene influenzato l'oggetto originario, appunto perché
il passaggio è per valore.
In un passaggio per riferimento [per esempio in C# usando la keyword ref]
modificando la variabile nel metodo chiamato viene modificata anche la
variabile nel metodo chiamante, perché viene passato il riferimento alla
variabile.
In Java si possono modificare gli oggetti in un metodo chiamato perché le
due variabili, diverse, puntano allo stesso oggetto.
Spero di essere stato chiaro... :-)
-- 
Pietro	- 
http://www.pietroweb.tk
Linux Registered User #304991
Powered by MDK Linux Kernel 2.6.10