Tailles de tableau dynamique Java?

106

J'ai une classe - xClass, que je veux charger dans un tableau de xClass donc je la déclaration:

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

Cependant, je ne sais pas si j'aurai besoin de 10. Je peux avoir besoin de 8 ou 12 ou de tout autre nombre d'ailleurs. Je ne le saurai pas avant l'exécution. Puis-je modifier le nombre d'éléments dans un tableau à la volée? Si c'est le cas, comment?

Paul
la source
J'ai corrigé le formatage de la question, vous pouvez juste le titre si vous le souhaitez, soyez juste descriptif. et bienvenue sur stackoverflow! : D
Gordon Gustafson

Réponses:

164

Non, vous ne pouvez pas modifier la taille d'un tableau une fois créé. Vous devez soit l'allouer plus grand que ce dont vous pensez avoir besoin ou accepter les frais généraux liés à la réaffectation nécessaire pour augmenter la taille. Quand c'est le cas, vous devrez en allouer un nouveau et copier les données de l'ancien vers le nouveau:

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;

Si vous vous trouvez dans cette situation, je vous recommande vivement d'utiliser les collections Java à la place. En particulier, ArrayListencapsule essentiellement un tableau et prend en charge la logique de croissance du tableau selon les besoins:

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

En général, une ArrayListsolution est préférable à un tableau de toute façon pour plusieurs raisons. D'une part, les tableaux sont mutables. Si vous avez une classe qui fait cela:

class Myclass {
    private int[] items;

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

vous avez créé un problème car un appelant peut modifier votre membre de données privées, ce qui conduit à toutes sortes de copies défensives. Comparez cela à la version List:

class Myclass {
    private List<Integer> items;

    public List<Integer> getItems() {
        return Collections.unmodifiableList(items);
    }
}
cletus
la source
1
List est l'interface et ArrayList est l'implémentation. Le créer en tant que ArrayList mais y faire référence en tant que List (afin qu'il puisse changer plus tard) est correct.
CBGraham
26

En java, la longueur du tableau est fixe.

Vous pouvez utiliser une liste pour contenir les valeurs et appeler la toArrayméthode si nécessaire. Consultez l'exemple suivant:

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
la source
8

Comme d'autres l'ont dit, vous ne pouvez pas modifier la taille d'un tableau Java existant.

ArrayList est le plus proche de Java standard d'un tableau de taille dynamique. Cependant, il y a certaines choses à propos de ArrayList (en fait l'interface de liste) qui ne sont pas "comme un tableau". Par exemple:

  • Vous ne pouvez pas utiliser [ ... ]pour indexer une liste. Vous devez utiliser les méthodes get(int)et set(int, E).
  • Un ArrayList est créé avec zéro élément. Vous ne pouvez pas simplement créer une ArrayList avec 20 éléments, puis appeler set(15, foo).
  • Vous ne pouvez pas modifier directement la taille d'un ArrayList. Vous le faites indirectement en utilisant les différents add, insertet des removeméthodes.

Si vous voulez quelque chose de plus semblable à un tableau, vous devrez concevoir votre propre API. (Peut-être que quelqu'un pourrait intervenir avec une bibliothèque tierce existante ... Je n'ai pas pu en trouver une avec 2 minutes de "recherche" avec Google :-))

Si vous n'avez vraiment besoin que d'un tableau qui grandit au fur et à mesure que vous l'initialisez , la solution est quelque chose comme ça.

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
la source
7

Vous définissez le nombre d'éléments sur tout ce que vous voulez au moment où vous le créez:

xClass[] mysclass = new xClass[n];

Ensuite, vous pouvez initialiser les éléments dans une boucle. Je suppose que c'est ce dont vous avez besoin.

Si vous avez besoin d'ajouter ou de supprimer des éléments au tableau après l'avoir créé, vous devez utiliser un fichier ArrayList.

newacct
la source
6

Vous pouvez utiliser 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());
Pascal9x
la source
3

Arrays.copyOf() La méthode a de nombreuses options pour résoudre le problème avec l'augmentation dynamique de la longueur du tableau.

API Java

homme.2067067
la source
Pour être précis: if (i> = mysclass.length) mysclass = Arrays.copyOf (mysclass, i + 1); mysclass [i] = new MyClass ();
Micha Berger
2

Oui, enveloppez-le et utilisez le framework Collections.

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

Utilisez ensuite List.toArray () si nécessaire, ou parcourez simplement cette liste.

File d'attente Jé
la source
2

Comme le disent d'autres utilisateurs, vous avez probablement besoin d'une implémentation de java.util.List.

Si, pour une raison quelconque, vous avez finalement besoin d'un tableau, vous pouvez faire deux choses:

  • Utilisez une liste puis convertissez-la en tableau avec myList.toArray ()

  • Utilisez un tableau d'une certaine taille. Si vous avez besoin de plus ou moins de taille, vous pouvez la modifier avec les méthodes java.util.Arrays.

La meilleure solution dépendra de votre problème;)

sinuhepop
la source
2

Je recommande d'utiliser des vecteurs à la place. Très facile à utiliser et dispose de nombreuses méthodes de mise en œuvre prédéfinies.

import java.util.*;

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

pour ajouter un élément utilisez simplement:

v.addElement(int);

Dans le (5,2), le premier 5 est la taille initiale du vecteur. Si vous dépassez la taille initiale, le vecteur augmentera de 2 places. S'il dépasse à nouveau, il augmentera à nouveau de 2 places et ainsi de suite.

Shashank Raghunath
la source
4
Sauf si vous avez spécifiquement besoin d'un type thread-safe (-ish), vous devez utiliser ArrayList plutôt que Vector.
Stephen C
1

Où vous déclarez le tableau myclass [] comme:

xClass myclass[] = new xClass[10]

, transmettez simplement comme argument le nombre d'éléments XClass dont vous aurez besoin. À ce stade, savez-vous de combien vous en aurez besoin? En déclarant le tableau comme ayant 10 éléments, vous ne déclarez pas 10 objets XClass, vous créez simplement un tableau avec 10 éléments de type xClass.

Amir Afghani
la source
1

Les tailles des tableaux Java sont fixes, vous ne pouvez pas créer de tableaux dynamiques comme celui de C ++.


la source
0

Il est recommandé d'obtenir la quantité que vous devez d'abord stocker, puis d'initialiser la baie.

par exemple, vous demanderiez à l'utilisateur combien de données il a besoin de stocker, puis l'initialisez, ou interrogez le composant ou l'argument sur le nombre de données à stocker. si vous voulez un tableau dynamique que vous pouvez utiliser ArrayList()et utiliser une al.add();fonction pour continuer à ajouter, vous pouvez le transférer dans un tableau fixe.

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

cela est redondant, mais juste pour vous montrer l'idée, ArrayListpeut contenir des objets contrairement aux autres types de données primitifs et est très facile à manipuler, supprimer tout ce qui se trouve au milieu est également facile, complètement dynamique List.Stack

Bakz
la source
0

Je ne sais pas si vous pouvez modifier la taille au moment de l'exécution, mais vous pouvez allouer la taille au moment de l'exécution. Essayez d'utiliser ce 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];
    }
}

cela affecte la taille de votre tableau à celle entrée au moment de l'exécution dans x.

Maranatha
la source
0

Voici une méthode qui n'utilise pas ArrayList. L'utilisateur spécifie la taille et vous pouvez ajouter une boucle do-while pour la récursivité.

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
la source
0

Dans Java, les tailles de tableau sont toujours de longueur fixe, mais il existe un moyen d'augmenter dynamiquement la taille de la matrice lors de l'exécution elle-même.

C'est la manière la plus "utilisée" et la plus préférée de le faire.

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

Dans le code ci-dessus, nous initialisons un nouveau tableau temp [], et en outre, nous utilisons une boucle for pour initialiser le contenu du temp avec le contenu du tableau d'origine, c'est-à-dire. stck []. Et puis de nouveau le recopier dans l'original, nous donnant un nouveau tableau de nouveau SIZE.

Il ne fait aucun doute qu'il génère une surcharge du processeur en raison de la réinitialisation répétée d'un tableau en utilisant la boucle for. Mais vous pouvez toujours l'utiliser et l'implémenter dans votre code. Pour la meilleure pratique, utilisez "Linked List" au lieu de Array, si vous voulez que les données soient stockées dynamiquement dans la mémoire, de longueur variable.

Voici un exemple en temps réel basé sur des piles dynamiques pour AUGMENTER LA TAILLE DU TABLEAU au moment de l'exécution

Nom de fichier: 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();
}

}

Nom de fichier: Exec.java
(avec 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);

}

}

J'espère que cela résout votre requête.

Jatin Chauhan
la source
0

Oui, nous pouvons le faire.

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
la source
0

Étant donné qu'ArrayList prend trop de mémoire lorsque j'ai besoin d'un tableau de types primitifs, je préfère utiliser IntStream.builder () pour créer un tableau int (vous pouvez également utiliser les générateurs LongStream et DoubleStream).

Exemple:

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

Remarque: disponible depuis Java 8.

Bosko Popovic
la source
0

Tu peux faire quelque chose

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
la source