Dynamische Java-Array-Größen?

106

Ich habe eine Klasse - xClass, die ich in ein Array von xClass laden möchte, damit ich die Deklaration:

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

Ich weiß jedoch nicht, ob ich 10 benötige. Möglicherweise benötige ich 8 oder 12 oder eine andere Nummer. Ich werde es erst zur Laufzeit wissen. Kann ich die Anzahl der Elemente in einem Array im laufenden Betrieb ändern? Wenn das so ist, wie?

Paul
quelle
Ich habe die Formatierung der Frage korrigiert, Sie können nur den Titel, wenn Sie wollen, nur beschreibend sein. und willkommen bei stackoverflow! : D
Gordon Gustafson

Antworten:

164

Nein, Sie können die Größe eines einmal erstellten Arrays nicht ändern. Entweder müssen Sie es größer zuweisen, als Sie denken, oder Sie müssen den Aufwand für die Neuzuweisung akzeptieren, um an Größe zu gewinnen. Wenn dies der Fall ist, müssen Sie eine neue zuweisen und die Daten von der alten in die neue kopieren:

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;

Wenn Sie sich in dieser Situation befinden, würde ich die Verwendung der Java-Sammlungen dringend empfehlen. Insbesondere ArrayListumschließt ein Array im Wesentlichen und kümmert sich um die Logik zum Erweitern des Arrays nach Bedarf:

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

Im Allgemeinen ArrayListist aus mehreren Gründen ohnehin eine bevorzugte Lösung für ein Array. Zum einen sind Arrays veränderlich. Wenn Sie eine Klasse haben, die dies tut:

class Myclass {
    private int[] items;

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

Sie haben ein Problem erstellt, da ein Anrufer Ihr privates Datenelement ändern kann, was zu allen Arten von defensivem Kopieren führt. Vergleichen Sie dies mit der Listenversion:

class Myclass {
    private List<Integer> items;

    public List<Integer> getItems() {
        return Collections.unmodifiableList(items);
    }
}
Cletus
quelle
1
List ist die Schnittstelle und ArrayList ist die Implementierung. Es ist korrekt, es als ArrayList zu erstellen, aber als Liste zu bezeichnen (damit es sich später ändern kann).
CBGraham
26

In Java ist die Array-Länge festgelegt.

Sie können eine Liste verwenden, um die Werte zu speichern und die toArrayMethode bei Bedarf aufzurufen. Siehe folgendes Beispiel:

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 {}
OscarRyz
quelle
8

Wie bereits erwähnt, können Sie die Größe eines vorhandenen Java-Arrays nicht ändern.

ArrayList ist diejenige, die Standard-Java einem Array mit dynamischer Größe am nächsten kommt. Es gibt jedoch einige Dinge an ArrayList (eigentlich die List-Schnittstelle), die nicht "Array-ähnlich" sind. Beispielsweise:

  • Sie können keine [ ... ]Liste indizieren. Sie müssen die Methoden get(int)und set(int, E)verwenden.
  • Eine ArrayList wird mit null Elementen erstellt. Sie können nicht einfach eine ArrayList mit 20 Elementen erstellen und dann aufrufen set(15, foo).
  • Sie können die Größe einer ArrayList nicht direkt ändern. Sie tun es , indirekt die verschiedenen Verwendung add, insertund removeMethoden.

Wenn Sie etwas Array-ähnlicheres möchten, müssen Sie Ihre eigene API entwerfen. (Vielleicht könnte sich jemand in eine vorhandene Bibliothek eines Drittanbieters einmischen ... Ich konnte keine mit 2 Minuten "Recherche" mit Google finden :-))

Wenn Sie wirklich nur ein Array benötigen, das beim Initialisieren wächst , ist die Lösung ungefähr so.

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()]);
Stephen C.
quelle
7

Sie legen die Anzahl der Elemente zum Zeitpunkt der Erstellung auf einen beliebigen Wert fest:

xClass[] mysclass = new xClass[n];

Anschließend können Sie die Elemente in einer Schleife initialisieren. Ich vermute, dass Sie das brauchen.

Wenn Sie dem Array nach dem Erstellen Elemente hinzufügen oder entfernen müssen, müssen Sie ein verwenden ArrayList.

newacct
quelle
6

Sie können ArrayList verwenden:

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());
Pascal9x
quelle
3

Arrays.copyOf() Die Methode bietet viele Optionen, um das Problem zu beheben, wenn die Array-Länge dynamisch zunimmt.

Java API

man.2067067
quelle
Um genau zu sein: if (i> = mysclass.length) mysclass = Arrays.copyOf (mysclass, i + 1); mysclass [i] = new MyClass ();
Micha Berger
2

Ja, wickeln Sie es ein und verwenden Sie das Collections-Framework.

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

Verwenden Sie dann bei Bedarf List.toArray () oder iterieren Sie einfach über diese Liste.

Jé Queue
quelle
2

Wie andere Benutzer sagen, benötigen Sie wahrscheinlich eine Implementierung von java.util.List.

Wenn Sie aus irgendeinem Grund endlich ein Array benötigen, können Sie zwei Dinge tun:

  • Verwenden Sie eine Liste und konvertieren Sie sie dann mit myList.toArray () in ein Array.

  • Verwenden Sie ein Array bestimmter Größe. Wenn Sie mehr oder weniger Größe benötigen, können Sie diese mit den Methoden java.util.Arrays ändern.

Die beste Lösung hängt von Ihrem Problem ab;)

Sinuhepop
quelle
2

Ich empfehle stattdessen Vektoren zu verwenden. Sehr einfach zu bedienen und verfügt über viele vordefinierte Methoden zur Implementierung.

import java.util.*;

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

Um ein Element hinzuzufügen, verwenden Sie einfach:

v.addElement(int);

In (5,2) ist die erste 5 die Anfangsgröße des Vektors. Wenn Sie die ursprüngliche Größe überschreiten, wächst der Vektor um 2 Stellen. Wenn es wieder überschreitet, erhöht es sich erneut um 2 Stellen und so weiter.

Shashank Raghunath
quelle
4
Sofern Sie nicht speziell einen thread-sicheren (-ish) Typ benötigen, sollten Sie ArrayList anstelle von Vector verwenden.
Stephen C
1

Wo Sie das Array myclass [] deklarieren als:

xClass myclass[] = new xClass[10]

Geben Sie einfach als Argument die Anzahl der benötigten XClass-Elemente ein. Wissen Sie zu diesem Zeitpunkt, wie viele Sie benötigen werden? Wenn Sie das Array mit 10 Elementen deklarieren, deklarieren Sie nicht 10 XClass-Objekte, sondern erstellen einfach ein Array mit 10 Elementen vom Typ xClass.

Amir Afghani
quelle
1

Java-Array-Größen sind fest. Sie können keine dynamischen Arrays wie in C ++ erstellen.


quelle
0

Es wird empfohlen, zuerst die Menge zu ermitteln, die Sie speichern müssen, und dann das Array zu initialisieren.

Beispielsweise würden Sie den Benutzer fragen, wie viele Daten er speichern und dann initialisieren muss, oder die Komponente oder das Argument abfragen, wie viele Sie speichern müssen. Wenn Sie ein dynamisches Array möchten, das Sie verwenden ArrayList()und mit der al.add();Funktion weiter hinzufügen können, können Sie es auf ein festes Array übertragen.

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

Dabei ist überflüssig , aber nur Sie auf die Idee zu zeigen, ArrayListkann Objekte im Gegensatz zu anderen primitiven Datentypen hält und ist sehr leicht zu manipulieren, etwas von der Mitte entfernt einfach wie gut ist, vollständig dynamic.same mit ListundStack

bakz
quelle
0

Ich weiß nicht, ob Sie die Größe zur Laufzeit ändern können, aber Sie können die Größe zur Laufzeit zuweisen. Versuchen Sie es mit diesem Code:

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];
    }
}

Dadurch wird Ihre Arraygröße der zur Laufzeit in x eingegebenen Größe zugewiesen.

Maranatha
quelle
0

Hier ist eine Methode, die ArrayList nicht verwendet. Der Benutzer gibt die Größe an und Sie können eine Do-While-Schleife für die Rekursion hinzufügen.

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);
        }
    }
wallace_stev
quelle
0

In Java haben Array-Größen immer eine feste Länge. Es gibt jedoch eine Möglichkeit, die Größe des Arrays zur Laufzeit selbst dynamisch zu erhöhen

Dies ist der am häufigsten verwendete und bevorzugte Weg, dies zu tun.

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

Im obigen Code initialisieren wir ein neues temp [] -Array und verwenden ferner eine for-Schleife, um den Inhalt des temp mit dem Inhalt des ursprünglichen Arrays zu initialisieren, d. H. stck []. Und dann kopieren Sie es wieder auf das Original zurück und erhalten eine neue Reihe neuer GRÖSSEN.

Zweifellos wird ein CPU-Overhead generiert, da ein Array mit der for-Schleife wiederholt neu initialisiert wird. Sie können es jedoch weiterhin in Ihrem Code verwenden und implementieren. Verwenden Sie für die beste Vorgehensweise "Verknüpfte Liste" anstelle von Array, wenn die Daten dynamisch im Speicher mit variabler Länge gespeichert werden sollen.

Hier ist ein Echtzeitbeispiel basierend auf dynamischen Stapeln, um die ARRAY-GRÖSSE zur Laufzeit zu erhöhen

Dateiname: 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();
}

}

Dateiname: Exec.java
(mit der Hauptklasse)

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

}

}

Hoffe das löst deine Frage.

Jatin Chauhan
quelle
0

Ja, wir können das so machen.

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


}
Jyoti Bhushan
quelle
0

Da ArrayList zu viel Speicher benötigt, wenn ich ein Array primitiver Typen benötige, bevorzuge ich die Verwendung von IntStream.builder () zum Erstellen von int-Arrays (Sie können auch LongStream- und DoubleStream-Builder verwenden).

Beispiel:

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

Hinweis: Verfügbar seit Java 8.

Bosko Popovic
quelle
0

Sie können etwas tun

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

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

    return personsArrayNew;

}
Chinthaka Devinda
quelle