Copia di array

di il
6 risposte

Copia di array

Ciao a tutti, nel modificare la dimensione di un array, mi sono accorto che Java lo "resetta", quindi sto provando un altro metodo, ovvero quello di salvare momentaneamente tutto in un array provvisorio e, dopo il cambio di dimensione, riportare tutto nell'array principale; il tutto avviene solo se la nuova dimensione è maggiore di quella precedente

Ho utilizzato System.arraycopy, ma avrei potuto utilizzare anche un ciclo for, il problema è che nessuno dei due funziona...intendo dire che l'array viene resettato...qualcuno saprebbe dirmi dove ho sbagliato? (Se richiesto, invierò le altre classi)
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
    Scanner s= new Scanner(System.in);
    Lista l;
    System.out.println("Inserisci dimensione: ");
    int n=s.nextInt();
    l= new Lista(n);
    int scelta;
        do {
        System.out.println("1) Inserisci elementi");
        System.out.println("2) Cerca diplomatico più anziano");
        System.out.println("3) Cerca cittadinanze uguali");
        System.out.println("4) Stampa elementi");
        System.out.println("5) Modifica dimensione");
        System.out.println("9) Uscita");
        scelta=s.nextInt();
        switch (scelta) 
           {
            case 1:
                l.inserimento();
                break;
            case 2:
                l.diplomatcoPiuVecchio();
                break;
            case 3:    
                l.cittadinanzaUguale();
                break;
            case 4:    
                l.stampa();
                break;
            case 5:
                System.out.println("Inserisci nuova dimensione: ");
                int newDim = s.nextInt();
                if(newDim > n){
                System.arraycopy(l.lista, 0, l.temp, 0, n);
                    l=new Lista(newDim);
                System.arraycopy(l.temp, 0, l.lista, 0, n);
                }
                break;        
           }     
     }while (scelta!=9);
    }
}

6 Risposte

  • Re: Copia di array

    sussolini ha scritto:


    Ciao a tutti, nel modificare la dimensione di un array, mi sono accorto che Java lo "resetta"
    Gli array in Java NON sono "ridimensionabili". Per espandere, bisogna creare un nuovo array (di dimensione più ampia) e facendo new Tipo[n] gli elementi del nuovo array sono tutti al loro valore di "default" (0, 0.0, false, null a seconda del tipo). Java garantisce che non vedi mai dati "spazzatura" negli array (come invece purtroppo avviene in C/C++).

    sussolini ha scritto:


    quindi sto provando un altro metodo, ovvero quello di salvare momentaneamente tutto in un array provvisorio e, dopo il cambio di dimensione, riportare tutto nell'array principale; il tutto avviene solo se la nuova dimensione è maggiore di quella precedente

    Ho utilizzato System.arraycopy, ma avrei potuto utilizzare anche un ciclo for, il problema è che nessuno dei due funziona...intendo dire che l'array viene resettato...qualcuno saprebbe dirmi dove ho sbagliato? (Se richiesto, invierò le altre classi)
    Non hai mostrato come è fatta la classe Lista. La questione sta tutta lì dentro. Ma c'è anche un aspetto di design che devi comprendere. Se hai una tua classe apposita che gestisce una "lista" (di qualunque cosa, non importa), la logica della espansione va inserita e incapsulata lì dentro. Tu dall'esterno NON devi fare cose con System.arraycopy puntando "dentro" l'oggetto con l.temp, l.lista ecc.. Questa logica va "nascosta" dentro la classe Lista.

    E per chiarire in modo più completo, sappi che ci sono tipicamente 2 tecniche per espandere logicamente un array.

    1) ad ogni singolo inserimento di un elemento si crea un nuovo array di lunghezza +1 e si aggiunge al fondo il nuovo elemento. E' facile da fare ma lo svantaggio è che si istanzia un nuovo array ad ogni inserimento.

    2) si gestisce l'array a capacità molto più espansa, in pratica come fanno le collection ArrayList e Vector. Oltre all'array si mantiene anche il numero "logico" di elementi. Si crea un nuovo array solo quando la capacità fisica non è più sufficiente e il nuovo array non si allunga solo di +1 ma molto di più (tipicamente il doppio o giù di lì ..). E' più difficile da gestire ma il vantaggio è che il "costo" della espansione viene "ammortizzato" nel tempo.

    Scegli quale tecnica usare.
  • Re: Copia di array

    andbin ha scritto:


    sussolini ha scritto:


    Ciao a tutti, nel modificare la dimensione di un array, mi sono accorto che Java lo "resetta"
    Gli array in Java NON sono "ridimensionabili". Per espandere, bisogna creare un nuovo array (di dimensione più ampia) e facendo new Tipo[n] gli elementi del nuovo array sono tutti al loro valore di "default" (0, 0.0, false, null a seconda del tipo). Java garantisce che non vedi mai dati "spazzatura" negli array (come invece purtroppo avviene in C/C++).

    sussolini ha scritto:


    quindi sto provando un altro metodo, ovvero quello di salvare momentaneamente tutto in un array provvisorio e, dopo il cambio di dimensione, riportare tutto nell'array principale; il tutto avviene solo se la nuova dimensione è maggiore di quella precedente

    Ho utilizzato System.arraycopy, ma avrei potuto utilizzare anche un ciclo for, il problema è che nessuno dei due funziona...intendo dire che l'array viene resettato...qualcuno saprebbe dirmi dove ho sbagliato? (Se richiesto, invierò le altre classi)
    Non hai mostrato come è fatta la classe Lista. La questione sta tutta lì dentro. Ma c'è anche un aspetto di design che devi comprendere. Se hai una tua classe apposita che gestisce una "lista" (di qualunque cosa, non importa), la logica della espansione va inserita e incapsulata lì dentro. Tu dall'esterno NON devi fare cose con System.arraycopy puntando "dentro" l'oggetto con l.temp, l.lista ecc.. Questa logica va "nascosta" dentro la classe Lista.

    E per chiarire in modo più completo, sappi che ci sono tipicamente 2 tecniche per espandere logicamente un array.

    1) ad ogni singolo inserimento di un elemento si crea un nuovo array di lunghezza +1 e si aggiunge al fondo il nuovo elemento. E' facile da fare ma lo svantaggio è che si istanzia un nuovo array ad ogni inserimento.

    2) si gestisce l'array a capacità molto più espansa, in pratica come fanno le collection ArrayList e Vector. Oltre all'array si mantiene anche il numero "logico" di elementi. Si crea un nuovo array solo quando la capacità fisica non è più sufficiente e il nuovo array non si allunga solo di +1 ma molto di più (tipicamente il doppio o giù di lì ..). E' più difficile da gestire ma il vantaggio è che il "costo" della espansione viene "ammortizzato" nel tempo.

    Scegli quale tecnica usare.
    ah, comunque ecco la classe Lista, ne mostro solo una parte (quella che dovrebbe star creando problemi), evito di mostrare il restante perchè non credo serva nella risoluzione del problema e potrebbe solo creare confusione

    premessa che avrei dovuto fare all'inizio: sono agli inizi del linguaggio Java
    import java.util.Scanner;
    public class Lista 
    {
        Scanner s= new Scanner(System.in);
      public Cittadino lista[];
      public Cittadino temp[];
      private int dim;
      public Lista(int n)
          { dim = n;
            lista = new Cittadino[dim];
            temp = new Cittadino[dim];
          }
  • Re: Copia di array

    sussolini ha scritto:


    public class Lista 
    {
        Scanner s= new Scanner(System.in);
      public Cittadino lista[];
      public Cittadino temp[];
    
    Non serve affatto l'array temp.

    Basta semplicemente

    private Cittadino[] lista;

    (le [] per convenzione si mettono vicino al tipo)

    Poi nel inserimento() fai:
    1) crei un nuovo array di dimensione +1 e lo assegni ad una variabile locale (ecco perché quella temp di istanza NON serve).
    2) usi System.arraycopy per copiare dal vecchio al nuovo
    3) assegni a lista (la variabile di istanza) il riferimento del nuovo array che hai nella variabile locale
    4) setti al fondo il nuovo elemento

    Si può anche semplificare usando il metodo copyOf di java.util.Arrays che combina insieme 1) 2) 3) ma devi sapere se puoi usarlo (per questioni "didattiche") o no.
  • Re: Copia di array

    andbin ha scritto:


    sussolini ha scritto:


    public class Lista 
    {
        Scanner s= new Scanner(System.in);
      public Cittadino lista[];
      public Cittadino temp[];
    
    Non serve affatto l'array temp.

    Basta semplicemente

    private Cittadino[] lista;

    (le [] per convenzione si mettono vicino al tipo)

    Poi nel inserimento() fai:
    1) crei un nuovo array di dimensione +1 e lo assegni ad una variabile locale (ecco perché quella temp di istanza NON serve).
    2) usi System.arraycopy per copiare dal vecchio al nuovo
    3) assegni a lista (la variabile di istanza) il riferimento del nuovo array che hai nella variabile locale
    4) setti al fondo il nuovo elemento

    Si può anche semplificare usando il metodo copyOf di java.util.Arrays che combina insieme 1) 2) 3) ma devi sapere se puoi usarlo (per questioni "didattiche") o no.
    ok, ho usato il copyOf
    ora mi ritrovo con questo
    case 5:
                    System.out.println("Inserisci nuova dimensione: ");
                    int newDim = s.nextInt();
                    if(newDim > n){
                        Cittadino[] copia=Arrays.copyOf(l.lista, newDim);
                        
                    }
                    break;       
    adesso, se l'array principale non è ridimensionabile mantenendo tutti i dati inseriti prima della modifica, vorrà dire che per tutto il resto del programma dovrò utilizzare l'array "copia" piuttosto dell'array "lista" (ovviamente dopo che il programma eseguirà il case 5), giusto?
    Se sì, come potrei fare?
  • Re: Copia di array

    sussolini ha scritto:


    adesso, se l'array principale non è ridimensionabile mantenendo tutti i dati inseriti prima della modifica, vorrà dire che per tutto il resto del programma dovrò utilizzare l'array "copia" piuttosto dell'array "lista" (ovviamente dopo che il programma eseguirà il case 5), giusto?
    Come ho già detto prima, dal main (e in generale dall'esterno della tua Lista), non dovresti "puntare" dentro l'oggetto Lista per manipolare il suo array interno. È la classe Lista che deve incapsulare e nascondere questa logica.

    Guarda questo esempio di lista di stringhe che ho scritto al volo.
    public class Prova {
        public static void main(String[] args) {
            ListaStringhe ls = new ListaStringhe();
            ls.aggiungi("Uno");
            ls.aggiungi("Due");
            ls.aggiungi("Tre");
        }
    }
    import java.util.Arrays;
    
    public class ListaStringhe {
        private String[] stringhe;
    
        public ListaStringhe() {
            stringhe = new String[0];
        }
    
        public void aggiungi(String stringa) {
            stringhe = Arrays.copyOf(stringhe, stringhe.length + 1);
            stringhe[stringhe.length - 1] = stringa;
        }
    
        // altri metodi ......
    }
    Il main non "sa" nulla dell'array interno a ListaStringhe, né lo manipola direttamente in qualche modo (non potrebbe nemmeno, essendo private). La logica di espansione è incapsulata e nascosta dentro ListaStringhe nel metodo aggiungi.
  • Re: Copia di array

    andbin ha scritto:


    sussolini ha scritto:


    adesso, se l'array principale non è ridimensionabile mantenendo tutti i dati inseriti prima della modifica, vorrà dire che per tutto il resto del programma dovrò utilizzare l'array "copia" piuttosto dell'array "lista" (ovviamente dopo che il programma eseguirà il case 5), giusto?
    Come ho già detto prima, dal main (e in generale dall'esterno della tua Lista), non dovresti "puntare" dentro l'oggetto Lista per manipolare il suo array interno. È la classe Lista che deve incapsulare e nascondere questa logica.

    Guarda questo esempio di lista di stringhe che ho scritto al volo.
    public class Prova {
        public static void main(String[] args) {
            ListaStringhe ls = new ListaStringhe();
            ls.aggiungi("Uno");
            ls.aggiungi("Due");
            ls.aggiungi("Tre");
        }
    }
    import java.util.Arrays;
    
    public class ListaStringhe {
        private String[] stringhe;
    
        public ListaStringhe() {
            stringhe = new String[0];
        }
    
        public void aggiungi(String stringa) {
            stringhe = Arrays.copyOf(stringhe, stringhe.length + 1);
            stringhe[stringhe.length - 1] = stringa;
        }
    
        // altri metodi ......
    }
    Il main non "sa" nulla dell'array interno a ListaStringhe, né lo manipola direttamente in qualche modo (non potrebbe nemmeno, essendo private). La logica di espansione è incapsulata e nascosta dentro ListaStringhe nel metodo aggiungi.
    sisi, infatti ho modificato, ora sta tutto nella classe Lista e in qualche modo adesso funziona, grazie per l'aiuto
Devi accedere o registrarti per scrivere nel forum
6 risposte