Dimensioni degli array dinamici Java?


106

Ho una classe - xClass, che voglio caricare in un array di xClass quindi ho la dichiarazione:

xClass mysclass[] = new xClass[10];
myclass[0] = new xClass();
myclass[9] = new xClass();

Tuttavia, non so se avrò bisogno di 10. Potrei aver bisogno di 8 o 12 o qualsiasi altro numero per quella materia. Non lo saprò fino al runtime. Posso modificare al volo il numero di elementi in un array? Se é cosi, come?


Ho sistemato la formattazione della domanda, puoi solo il titolo se vuoi, basta essere descrittivi. e benvenuto in stackoverflow! : D
Gordon Gustafson

Risposte:


164

No, non è possibile modificare la dimensione di un array una volta creato. Devi allocarlo più grande di quanto pensi di aver bisogno o accettare il sovraccarico di doverlo riallocare per crescere di dimensioni. Quando lo farà dovrai assegnarne uno nuovo e copiare i dati dal vecchio al nuovo:

int[] oldItems = new int[10];
for (int i = 0; i < 10; i++) {
    oldItems[i] = i + 10;
}
int[] newItems = new int[20];
System.arraycopy(oldItems, 0, newItems, 0, 10);
oldItems = newItems;

Se ti trovi in ​​questa situazione, ti consiglio vivamente di utilizzare invece le raccolte Java. In particolare ArrayListessenzialmente avvolge un array e si prende cura della logica per far crescere l'array come richiesto:

List<XClass> myclass = new ArrayList<XClass>();
myclass.add(new XClass());
myclass.add(new XClass());

Generalmente an ArrayListè comunque una soluzione preferibile a un array per diversi motivi. Per prima cosa, gli array sono mutabili. Se hai una classe che fa questo:

class Myclass {
    private int[] items;

    public int[] getItems() {
        return items;
    }
}

hai creato un problema in quanto un chiamante può modificare il tuo membro di dati privati, il che porta a tutti i tipi di copia difensiva. Confronta questo con la versione List:

class Myclass {
    private List<Integer> items;

    public List<Integer> getItems() {
        return Collections.unmodifiableList(items);
    }
}

1
List è l'interfaccia e ArrayList è l'implementazione. Crearlo come ArrayList ma riferirsi ad esso come List (in modo che possa cambiare in seguito) è corretto.
CBGraham

26

In java array la lunghezza è fissa.

È possibile utilizzare un elenco per contenere i valori e richiamare il toArraymetodo se necessario Vedere il seguente esempio:

import java.util.List;
import java.util.ArrayList;
import java.util.Random;

public class A  {

    public static void main( String [] args ) {
        // dynamically hold the instances
        List<xClass> list = new ArrayList<xClass>();

        // fill it with a random number between 0 and 100
        int elements = new Random().nextInt(100);  
        for( int i = 0 ; i < elements ; i++ ) {
            list.add( new xClass() );
        }

        // convert it to array
        xClass [] array = list.toArray( new xClass[ list.size() ] );


        System.out.println( "size of array = " + array.length );
    }
}
class xClass {}

8

Come altri hanno già detto, non è possibile modificare la dimensione di un array Java esistente.

ArrayList è il più vicino che Java standard ha a un array di dimensioni dinamiche. Tuttavia, ci sono alcune cose su ArrayList (in realtà l'interfaccia List) che non sono "come array". Per esempio:

  • Non è possibile utilizzare [ ... ]per indicizzare un elenco. Devi usare i metodi get(int)e set(int, E).
  • Viene creato un ArrayList con zero elementi. Non è possibile creare semplicemente un ArrayList con 20 elementi e quindi chiamare set(15, foo).
  • Non è possibile modificare direttamente la dimensione di un ArrayList. Lo si fa indirettamente utilizzando i vari add, inserte removemetodi.

Se vuoi qualcosa di più simile ad un array, dovrai progettare la tua API. (Forse qualcuno potrebbe intervenire con una libreria di terze parti esistente ... non sono riuscito a trovarne una con 2 minuti di "ricerca" utilizzando Google :-))

Se hai solo bisogno di un array che cresce man mano che lo stai inizializzando , la soluzione è qualcosa del genere.

ArrayList<T> tmp = new ArrayList<T>();
while (...) {
    tmp.add(new T(...));
}
// This creates a new array and copies the element of 'tmp' to it.
T[] array = tmp.toArray(new T[tmp.size()]);

7

Puoi impostare il numero di elementi su qualsiasi cosa desideri nel momento in cui lo crei:

xClass[] mysclass = new xClass[n];

Quindi puoi inizializzare gli elementi in un ciclo. Immagino che questo sia ciò di cui hai bisogno.

Se è necessario aggiungere o rimuovere elementi dall'array dopo averlo creato, è necessario utilizzare un file ArrayList.


6

Puoi usare ArrayList:

import java.util.ArrayList;
import java.util.Iterator;

...

ArrayList<String> arr = new ArrayList<String>();
arr.add("neo");
arr.add("morpheus");
arr.add("trinity");
Iterator<String> foreach = arr.iterator();
while (foreach.hasNext()) System.out.println(foreach.next());

3

Arrays.copyOf() ha molte opzioni per risolvere il problema con la lunghezza dell'array che aumenta dinamicamente.

API Java


Per essere precisi: if (i> = mysclass.length) mysclass = Arrays.copyOf (mysclass, i + 1); mysclass [i] = nuova MyClass ();
Micha Berger

2

Sì, avvolgilo e usa il framework delle collezioni.

List l = new ArrayList();
l.add(new xClass());
// do stuff
l.add(new xClass());

Quindi utilizzare List.toArray () quando necessario, o semplicemente iterare su detto elenco.


2

Come dicono altri utenti, probabilmente hai bisogno di un'implementazione di java.util.List.

Se, per qualche motivo, hai finalmente bisogno di un array, puoi fare due cose:

  • Usa un elenco e poi convertilo in un array con myList.toArray ()

  • Usa un array di una certa dimensione. Se hai bisogno di dimensioni maggiori o minori, puoi modificarle con i metodi java.util.Arrays.

La migliore soluzione dipenderà dal tuo problema;)


2

Consiglio invece di usare i vettori. Molto facile da usare e ha molti metodi predefiniti per l'implementazione.

import java.util.*;

Vector<Integer> v=new Vector<Integer>(5,2);

per aggiungere un elemento è sufficiente utilizzare:

v.addElement(int);

Nella (5,2) il primo 5 è la dimensione iniziale del vettore. Se superi la dimensione iniziale, il vettore crescerà di 2 posizioni. Se supera di nuovo, aumenterà di nuovo di 2 posizioni e così via.


4
A meno che tu non abbia specificamente bisogno di un tipo thread-safe (-ish), dovresti usare ArrayList invece di Vector.
Stephen C

1

Dove dichiari l'array myclass [] come:

xClass myclass[] = new xClass[10]

, passa semplicemente come argomento il numero di elementi XClass di cui avrai bisogno. A quel punto sai di quanti ne avrai bisogno? Dichiarando che l'array ha 10 elementi, non stai dichiarando 10 oggetti XClass, stai semplicemente creando un array con 10 elementi di tipo xClass.


1

Le dimensioni degli array Java sono fisse, non è possibile creare array dinamici come in C ++.


0

È una buona pratica ottenere prima la quantità che è necessario memorizzare, quindi inizializzare l'array.

ad esempio, chiederesti all'utente quanti dati ha bisogno di memorizzare e quindi inizializzarli, o interrogare il componente o l'argomento di quanti dati devi memorizzare. se si desidera un array dinamico da utilizzare ArrayList()e utilizzare la al.add();funzione per continuare ad aggiungere, è possibile trasferirlo in un array fisso.

//Initialize ArrayList and cast string so ArrayList accepts strings (or anything
ArrayList<string> al = new ArrayList(); 
//add a certain amount of data
for(int i=0;i<x;i++)
{
  al.add("data "+i); 
}

//get size of data inside
int size = al.size(); 
//initialize String array with the size you have
String strArray[] = new String[size]; 
//insert data from ArrayList to String array
for(int i=0;i<size;i++)
{
  strArray[i] = al.get(i);
}

Così facendo è ridondante, ma solo per mostrare l'idea, ArrayListpuò contenere gli oggetti a differenza di altri tipi di dati primitivi e sono molto facili da manipolare, togliere nulla dalla metà è facile così, completamente dynamic.same con ListeStack


0

Non so se è possibile modificare la dimensione in fase di esecuzione, ma è possibile allocare la dimensione in fase di esecuzione. Prova a usare questo codice:

class MyClass {
    void myFunction () {
        Scanner s = new Scanner (System.in);
        int myArray [];
        int x;

        System.out.print ("Enter the size of the array: ");
        x = s.nextInt();

        myArray = new int[x];
    }
}

questo assegna la dimensione dell'array come quella inserita in fase di esecuzione in x.


0

Ecco un metodo che non utilizza ArrayList. L'utente specifica la dimensione e puoi aggiungere un ciclo di ripetizione per la ricorsione.

import java.util.Scanner;
    public class Dynamic {
        public static Scanner value;
        public static void main(String[]args){
            value=new Scanner(System.in);
            System.out.println("Enter the number of tests to calculate average\n");
            int limit=value.nextInt();
            int index=0;
            int [] marks=new int[limit];
            float sum,ave;
            sum=0;      
            while(index<limit)
            {
                int test=index+1;
                System.out.println("Enter the marks on test " +test);
                marks[index]=value.nextInt();
                sum+=marks[index];
                index++;
            }
            ave=sum/limit;
            System.out.println("The average is: " + ave);
        }
    }

0

In Java le dimensioni dell'array sono sempre di lunghezza fissa, ma esiste un modo in cui puoi aumentare dinamicamente la dimensione dell'array durante il runtime stesso

Questo è il modo più "usato" e preferito per farlo-

    int temp[]=new int[stck.length+1];
    for(int i=0;i<stck.length;i++)temp[i]=stck[i];
    stck=temp;

Nel codice sopra stiamo inizializzando un nuovo array temp [], e ulteriormente usando un ciclo for per inizializzare il contenuto del temp con il contenuto dell'array originale, es. Stck []. E poi di nuovo copiandolo di nuovo a quello originale, dandoci una nuova gamma di nuove TAGLIE.

Senza dubbio genera un sovraccarico della CPU dovuto alla reinizializzazione di un array utilizzando ripetutamente il ciclo for. Ma puoi ancora usarlo e implementarlo nel tuo codice. Per la migliore pratica, utilizzare "Elenco collegato" invece di Array, se si desidera che i dati vengano archiviati dinamicamente nella memoria, di lunghezza variabile.

Ecco un esempio in tempo reale basato su stack dinamici per AUMENTARE LA DIMENSIONE DELL'ARRAY in fase di esecuzione

Nome file: DStack.java

public class DStack {
private int stck[];
int tos;

void Init_Stck(int size) {
    stck=new int[size];
    tos=-1;
}
int Change_Stck(int size){
    return stck[size];
}

public void push(int item){
    if(tos==stck.length-1){
        int temp[]=new int[stck.length+1];
        for(int i=0;i<stck.length;i++)temp[i]=stck[i];
        stck=temp;
        stck[++tos]=item;
    }
    else
        stck[++tos]=item;
}
public int pop(){
    if(tos<0){
        System.out.println("Stack Underflow");
        return 0;
    }
    else return stck[tos--];
}

public void display(){
    for(int x=0;x<stck.length;x++){
        System.out.print(stck[x]+" ");
    }
    System.out.println();
}

}

Nome file: Exec.java
(con la classe principale)

import java.util.*;
public class Exec {

private static Scanner in;

public static void main(String[] args) {
    in = new Scanner(System.in);
    int option,item,i=1;
    DStack obj=new DStack();
    obj.Init_Stck(1);
    do{
        System.out.println();
        System.out.println("--MENU--");
        System.out.println("1. Push a Value in The Stack");
        System.out.println("2. Pop a Value from the Stack");
        System.out.println("3. Display Stack");
        System.out.println("4. Exit");
        option=in.nextInt();
        switch(option){
        case 1:
            System.out.println("Enter the Value to be Pushed");
            item=in.nextInt();
            obj.push(item);
            break;
        case 2:
            System.out.println("Popped Item: "+obj.pop());
            obj.Change_Stck(obj.tos);
            break;
        case 3:
            System.out.println("Displaying...");
            obj.display();
            break;
        case 4:
            System.out.println("Exiting...");
            i=0;
            break;
        default:
            System.out.println("Enter a Valid Value");

        }
    }while(i==1);

}

}

Spero che questo risolva la tua domanda.


0

Sì, possiamo farlo in questo modo.

import java.util.Scanner;

public class Collection_Basic {

    private static Scanner sc;

    public static void main(String[] args) {

        Object[] obj=new Object[4];
        sc = new Scanner(System.in);


        //Storing element
        System.out.println("enter your element");
        for(int i=0;i<4;i++){
            obj[i]=sc.nextInt();
        }

        /*
         * here, size reaches with its maximum capacity so u can not store more element,
         * 
         * for storing more element we have to create new array Object with required size
         */

        Object[] tempObj=new Object[10];

        //copying old array to new Array

        int oldArraySize=obj.length;
        int i=0;
        for(;i<oldArraySize;i++){

            tempObj[i]=obj[i];
        }

        /*
         * storing new element to the end of new Array objebt
         */
        tempObj[i]=90;

        //assigning new array Object refeence to the old one

        obj=tempObj;

        for(int j=0;j<obj.length;j++){
            System.out.println("obj["+j+"] -"+obj[j]);
        }
    }


}

0

Poiché ArrayList richiede molta memoria quando ho bisogno di array di tipi primitivi, preferisco usare IntStream.builder () per creare int array (puoi anche usare LongStream e DoubleStream builder).

Esempio:

Builder builder = IntStream.builder();
int arraySize = new Random().nextInt();
for(int i = 0; i<arraySize; i++ ) {
    builder.add(i);
}
int[] array = builder.build().toArray();

Nota: disponibile da Java 8.


0

Puoi fare qualcosa

private  static Person []  addPersons(Person[] persons, Person personToAdd) {
    int currentLenght = persons.length;

    Person [] personsArrayNew = Arrays.copyOf(persons, currentLenght +1);
    personsArrayNew[currentLenght]  = personToAdd;

    return personsArrayNew;

}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.