Rozmiary dynamicznych tablic Java?


106

Mam klasę - xClass, którą chcę załadować do tablicy xClass, więc mam deklarację:

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

Jednak nie wiem, czy będę potrzebować 10. Może potrzebuję 8, 12 lub jakakolwiek inna liczba. Nie dowiem się przed uruchomieniem. Czy mogę na bieżąco zmieniać liczbę elementów w tablicy? Jeśli tak to jak?


Poprawiłem formatowanie pytania, jeśli chcesz, możesz po prostu tytuł, po prostu opisowy. i witamy w stackoverflow! : D
Gordon Gustafson

Odpowiedzi:


164

Nie, nie możesz zmienić rozmiaru utworzonej tablicy. Musisz albo przydzielić więcej, niż myślisz, że będziesz potrzebować, lub zaakceptować koszty związane z ponownym przydzieleniem, które muszą wzrosnąć. Kiedy to nastąpi, będziesz musiał przydzielić nowy i skopiować dane ze starego do nowego:

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;

Jeśli znajdziesz się w takiej sytuacji, zdecydowanie polecam skorzystanie z kolekcji Java. W szczególności ArrayListzasadniczo otacza tablicę i dba o logikę powiększania tablicy zgodnie z wymaganiami:

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

Ogólnie rzecz biorąc, ArrayListjest to lepsze rozwiązanie niż macierz z kilku powodów. Po pierwsze, tablice są zmienne. Jeśli masz klasę, która to robi:

class Myclass {
    private int[] items;

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

stworzyłeś problem, ponieważ dzwoniący może zmienić prywatnego członka danych, co prowadzi do wszelkiego rodzaju kopiowania obronnego. Porównaj to z wersją listy:

class Myclass {
    private List<Integer> items;

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

1
List to interfejs, a ArrayList to implementacja. Utworzenie go jako ArrayList, ale odwołanie się do niego jako listy (aby można go było później zmienić) jest poprawne.
CBGraham

26

W java długość tablicy jest stała.

Możesz użyć listy do przechowywania wartości i wywoływania toArraymetody w razie potrzeby. Zobacz następujący przykład:

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

Jak powiedzieli inni, nie można zmienić rozmiaru istniejącej tablicy Java.

ArrayList to najbliższa standardowej Java tablica o rozmiarze dynamicznym. Jednak jest kilka rzeczy dotyczących ArrayList (właściwie interfejsu List), które nie są „podobne do tablic”. Na przykład:

  • Nie możesz używać [ ... ]do indeksowania listy. Musisz użyć metod get(int)i set(int, E).
  • ArrayList jest tworzona z zerowymi elementami. Nie można w prosty sposób utworzyć ArrayList z 20 elementami, a następnie wywołać set(15, foo).
  • Nie można bezpośrednio zmienić rozmiaru tablicy ArrayList. Robisz to pośrednio za pomocą różnych add, inserti removemetod.

Jeśli chcesz czegoś bardziej przypominającego tablicę, musisz zaprojektować własne API. (Może ktoś mógłby zadzwonić do istniejącej biblioteki innej firmy ... Nie mogłem znaleźć takiej, która miałaby 2 minuty wyszukiwania w Google :-))

Jeśli naprawdę potrzebujesz tylko tablicy, która rośnie w miarę jej inicjalizacji , rozwiązanie jest takie.

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

Możesz ustawić dowolną liczbę elementów w momencie tworzenia:

xClass[] mysclass = new xClass[n];

Następnie możesz zainicjować elementy w pętli. Domyślam się, że tego potrzebujesz.

Jeśli chcesz dodać lub usunąć elementy do tablicy po jej utworzeniu, musisz użyć rozszerzenia ArrayList.


6

Możesz użyć 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() metoda ma wiele opcji rozwiązania problemu z dynamicznym zwiększaniem długości tablicy.

Java API


Konkretnie: if (i> = mysclass.length) mysclass = Arrays.copyOf (mysclass, i + 1); mysclass [i] = new MyClass ();
Micha Berger

2

Tak, opakuj go i użyj struktury Kolekcje.

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

Następnie użyj List.toArray (), jeśli to konieczne, lub po prostu powtórz tę listę.


2

Jak mówią inni użytkownicy, prawdopodobnie potrzebujesz implementacji java.util.List.

Jeśli z jakiegoś powodu w końcu potrzebujesz tablicy, możesz zrobić dwie rzeczy:

  • Użyj listy, a następnie przekonwertuj ją na tablicę za pomocą myList.toArray ()

  • Użyj tablicy o określonym rozmiarze. Jeśli potrzebujesz większego lub mniejszego rozmiaru, możesz go zmodyfikować metodami java.util.Arrays.

Najlepsze rozwiązanie będzie zależeć od Twojego problemu;)


2

Zamiast tego zalecam używanie wektorów. Bardzo łatwy w użyciu i posiada wiele predefiniowanych metod implementacji.

import java.util.*;

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

aby dodać element po prostu użyj:

v.addElement(int);

W (5,2) pierwsze 5 to początkowa wielkość wektora. Jeśli przekroczysz rozmiar początkowy, wektor powiększy się o 2 miejsca. Jeśli przekroczy ponownie, ponownie wzrośnie o 2 miejsca i tak dalej.


4
O ile nie potrzebujesz konkretnego typu bezpiecznego dla wątków (-ish), powinieneś używać ArrayList zamiast Vector.
Stephen C

1

Gdzie deklarujesz tablicę myclass [] jako:

xClass myclass[] = new xClass[10]

, po prostu podaj jako argument liczbę potrzebnych elementów XClass. Czy w tym momencie wiesz, ile będziesz potrzebować? Deklarując tablicę jako posiadającą 10 elementów, nie deklarujesz 10 obiektów XClass, po prostu tworzysz tablicę z 10 elementami typu xClass.


1

Rozmiary tablic Java są stałe, nie można tworzyć tablic dynamicznych, jak w C ++.


0

Dobrą praktyką jest pobranie najpierw ilości, którą trzeba przechowywać, a następnie zainicjowanie macierzy.

na przykład można zapytać użytkownika, ile danych musi przechowywać, a następnie zainicjować je, lub zapytać o składnik lub argument, ile danych ma przechowywać. jeśli chcesz mieć tablicę dynamiczną, której możesz użyć ArrayList()i użyć al.add();funkcji do dalszego dodawania, możesz przenieść ją do stałej tablicy.

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

robienie tego jest zbędne, ale tylko po to, aby pokazać pomysł, ArrayListmoże przechowywać obiekty w przeciwieństwie do innych prymitywnych typów danych i jest bardzo łatwe w manipulowaniu, usuwanie czegokolwiek ze środka jest również łatwe, całkowicie dynamiczne. to samo z ListiStack


0

Nie wiem, czy możesz zmienić rozmiar w czasie wykonywania, ale możesz przydzielić rozmiar w czasie wykonywania. Spróbuj użyć tego kodu:

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

to przypisuje rozmiar twojej tablicy tak, aby był taki, jaki został wprowadzony w czasie wykonywania do x.


0

Oto metoda, która nie używa ArrayList. Użytkownik określa rozmiar i można dodać pętlę do-while dla rekurencji.

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

W Javie Rozmiary tablic mają zawsze stałą długość Ale jest sposób w jaki można dynamicznie zwiększyćrozmiar tablicy w czasie wykonywania

Jest to najbardziej „używany” i preferowany sposób.

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

W powyższym kodzie inicjalizujemy nową tablicę temp [], a następnie używamy pętli for do inicjalizacji zawartości temp z zawartością oryginalnej tablicy, tj. stck []. A potem ponownie kopiuję go z powrotem do pierwotnego, dając nam nowy zestaw nowych ROZMIARÓW.

Bez wątpienia generuje obciążenie procesora z powodu wielokrotnej inicjalizacji tablicy przy użyciu pętli for. Ale nadal możesz go używać i implementować w swoim kodzie. Najlepszym rozwiązaniem jest użycie „listy połączonej” zamiast tablicy, jeśli chcesz, aby dane były dynamicznie przechowywane w pamięci, o zmiennej długości.

Oto przykład czasu rzeczywistego oparty na dynamicznych stosach w celu ZWIĘKSZENIA ROZMIARU TABLICY w czasie wykonywania

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

}

Nazwa pliku: Exec.java
(z główną klasą)

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

}

}

Mam nadzieję, że to rozwiąże Twoje pytanie.


0

Tak, możemy to zrobić.

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

Ponieważ ArrayList zajmuje dużo pamięci, gdy potrzebuję tablicy typów pierwotnych, wolę używać IntStream.builder () do tworzenia tablicy int (można również użyć konstruktorów LongStream i DoubleStream).

Przykład:

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

Uwaga: dostępne od wersji Java 8.


0

Możesz coś zrobić

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

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

    return personsArrayNew;

}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.