Java dinamik dizi boyutları?


106

XClass dizisine yüklemek istediğim bir sınıfım var - xClass, bu yüzden bildirimi:

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

Ancak 10'a ihtiyacım olup olmayacağını bilmiyorum. Bunun için 8, 12 veya başka bir sayıya ihtiyacım olabilir. Çalışma zamanına kadar bilmeyeceğim. Bir dizideki elemanların sayısını anında değiştirebilir miyim? Öyleyse nasıl?


Sorunun biçimini düzelttim, isterseniz sadece başlığı kullanabilirsiniz, sadece açıklayıcı olun. ve stackoverflow'a hoş geldiniz! : D
Gordon Gustafson

Yanıtlar:


164

Hayır, oluşturulduktan sonra bir dizinin boyutunu değiştiremezsiniz. Ya ihtiyacınız olacağını düşündüğünüzden daha fazla tahsis etmeniz ya da boyut olarak büyümesi için ihtiyaç duyduğu yeniden tahsis etme yükünü kabul etmeniz gerekir. Bunu yaptığında, yeni bir tane ayırmanız ve verileri eskiden yeniye kopyalamanız gerekir:

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;

Kendinizi bu durumda bulursanız, bunun yerine Java Koleksiyonlarını kullanmanızı şiddetle tavsiye ederim. Özellikle, ArrayListesasen bir diziyi sarar ve diziyi gerektiği gibi büyütme mantığıyla ilgilenir:

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

Genel olarak bir ArrayList, çeşitli nedenlerle zaten bir diziye tercih edilen bir çözümdür. Birincisi, diziler değiştirilebilir. Bunu yapan bir sınıfınız varsa:

class Myclass {
    private int[] items;

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

Arayan bir kişi özel veri üyenizi değiştirebileceği için bir sorun yarattınız ve bu da her türlü savunma amaçlı kopyalamayı mümkün kılıyor. Bunu Liste sürümüyle karşılaştırın:

class Myclass {
    private List<Integer> items;

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

1
Liste arabirimdir ve ArrayList gerçeklemedir. Bunu bir ArrayList olarak oluşturmak, ancak ona bir Liste olarak başvurmak (böylece daha sonra değişebilir) doğrudur.
CBGraham

26

Java dizisinde uzunluk sabittir.

Değerleri tutmak ve toArraygerekirse yöntemi çağırmak için bir Liste kullanabilirsiniz Aşağıdaki örneğe bakın:

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

Başkalarının dediği gibi, mevcut bir Java dizisinin boyutunu değiştiremezsiniz.

ArrayList, standart Java'nın dinamik boyutlu bir diziye en yakın olanıdır. Bununla birlikte, ArrayList (aslında Liste arayüzü) hakkında "dizi benzeri" olmayan bazı şeyler vardır. Örneğin:

  • [ ... ]Bir listeyi indekslemek için kullanamazsınız . get(int)Ve set(int, E)yöntemlerini kullanmalısınız .
  • Sıfır elemanlı bir ArrayList oluşturulur. 20 öğeli bir ArrayList oluşturup ardından çağrı yapamazsınız set(15, foo).
  • Bir ArrayList'in boyutunu doğrudan değiştiremezsiniz. Sen dolaylı çeşitli kullanarak bunu add, insertve removeyöntemleri.

Daha dizi benzeri bir şey istiyorsanız, kendi API'nizi tasarlamanız gerekecektir. (Belki birisi mevcut bir üçüncü taraf kitaplığıyla iletişim kurabilir ... Google'ı kullanarak 2 dakikalık "araştırma" yapan bir kitap bulamadım :-))

Sadece siz onu başlatırken büyüyen bir diziye gerçekten ihtiyacınız varsa , çözüm bunun gibi bir şeydir.

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

Öğelerin sayısını, onu oluşturduğunuz sırada istediğiniz herhangi bir şeye ayarlarsınız:

xClass[] mysclass = new xClass[n];

Daha sonra bir döngüdeki öğeleri başlatabilirsiniz. Sanırım ihtiyacın olan bu.

Diziyi oluşturduktan sonra öğeleri eklemeniz veya kaldırmanız gerekirse, o zaman bir ArrayList.


6

ArrayList'i kullanabilirsiniz:

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() yöntemi, dizi uzunluğu dinamik olarak artan sorunu çözmek için birçok seçeneğe sahiptir.

Java API


Spesifik olmak gerekirse: if (i> = mysclass.length) mysclass = Arrays.copyOf (mysclass, i + 1); mysclass [i] = new Sınıfım ();
Micha Berger

2

Evet, sarın ve Koleksiyonlar çerçevesini kullanın.

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

Daha sonra gerektiğinde List.toArray () kullanın veya söz konusu List üzerinde yineleyin.


2

Diğer kullanıcıların dediği gibi, muhtemelen java.util.List uygulamasına ihtiyacınız vardır.

Herhangi bir nedenle, sonunda bir diziye ihtiyacınız varsa, iki şey yapabilirsiniz:

  • Bir Liste kullanın ve ardından bunu myList.toArray () ile bir diziye dönüştürün

  • Belirli boyutta bir dizi kullanın. Daha fazla veya daha küçük boyuta ihtiyacınız varsa, bunu java.util.Arrays yöntemleriyle değiştirebilirsiniz.

En iyi çözüm, sorununuza bağlı olacaktır;)


2

Bunun yerine vektörleri kullanmanızı tavsiye ederim. Kullanımı çok kolaydır ve uygulama için önceden tanımlanmış birçok yönteme sahiptir.

import java.util.*;

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

bir öğe eklemek için şunu kullanın:

v.addElement(int);

Olarak (5,2) ilk olarak 5 vektörün ilk boyutudur. Başlangıç ​​boyutunu aşarsanız, vektör 2 basamak büyür. Tekrar aşarsa, o zaman tekrar 2 sıra artar ve böyle devam eder.


4
Özellikle iş parçacığı güvenli (-ish) bir türe ihtiyacınız olmadığı sürece, Vector yerine ArrayList kullanmalısınız.
Stephen C

1

Sınıfım [] dizisini şu şekilde bildirdiğiniz yer:

xClass myclass[] = new xClass[10]

, ihtiyacınız olan XClass elemanlarının sayısını argüman olarak basitçe iletin. Bu noktada kaç tanesine ihtiyacınız olacağını biliyor musunuz? Diziyi 10 öğeye sahip olarak bildirerek, 10 XClass nesnesi bildirmezsiniz, yalnızca xClass türünde 10 öğeli bir dizi oluşturursunuz.


1

Java Dizi boyutları sabittir, C ++ 'da olduğu gibi dinamik Diziler oluşturamazsınız.


0

Önce saklamanız gereken miktarı elde edip ardından diziyi başlatmak iyi bir uygulamadır.

örneğin, kullanıcıya kaç veriyi depolaması ve ardından onu başlatması gerektiğini sorabilir veya kaç tane depolamanız gerektiğine dair bileşeni veya argümanı sorgulayabilirsiniz. Dinamik bir dizi istiyorsanız, eklemeye devam etmek için işlevi kullanabilir ArrayList()ve kullanabilirsiniz al.add();, o zaman onu sabit bir diziye aktarabilirsiniz.

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

bunu yapmak gereksizdir, ancak size sadece fikri göstermek için, ArrayListdiğer ilkel veri türlerinden farklı olarak nesneleri tutabilir ve manipüle edilmesi çok kolaydır, ortadaki herhangi bir şeyi kaldırmak da kolaydır, tamamen dinamiktir. ile aynı ListveStack


0

Çalışma zamanında boyutu değiştirebilir misiniz bilmiyorum ama boyutu çalışma zamanında tahsis edebilirsiniz. Bu kodu kullanmayı deneyin:

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

bu, dizi boyutunuzu çalışma zamanında x'e girilen boyut olarak atar.


0

İşte ArrayList kullanmayan bir yöntem. Kullanıcı boyutu belirtir ve özyineleme için bir do-while döngüsü ekleyebilirsiniz.

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

Java Dizisinde Boyutlar her zaman Sabit Uzunluktadır Ancak Dizinin Boyutunu Çalışma Zamanında Dinamik olarak artırmanın bir yolu vardır.

Bu, bunu yapmanın en "kullanılan" ve tercih edilen yoludur.

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

Yukarıdaki kodda, yeni bir temp [] dizisini başlatıyoruz ve ayrıca temp içeriğini orijinal dizinin içeriğiyle başlatmak için bir for döngüsü kullanıyoruz, yani. stck []. Ve sonra tekrar orijinal olana kopyalayıp bize yeni bir SIZE dizisi veriyor.

Hiç şüphe yok ki, tekrar tekrar for döngüsü kullanarak bir diziyi yeniden başlattığı için bir CPU Ek yükü oluşturuyor. Ancak yine de kodunuzda kullanabilir ve uygulayabilirsiniz. En iyi uygulama için, verilerin değişken uzunlukta bellekte dinamik olarak depolanmasını istiyorsanız, Dizi yerine "Bağlantılı Liste" kullanın.

İşte Çalışma Zamanında DİZİ BOYUTUNU ARTIRMAK için Dinamik Yığınlara dayalı bir Gerçek Zamanlı Örnek

Dosya adı: 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();
}

}

Dosya adı: Exec.java
(ana sınıfla)

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

}

}

Umarım bu, sorgunuzu çözer.


0

Evet, bu şekilde yapabiliriz.

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

ArrayList, ilkel türlerin dizisine ihtiyacım olduğunda çok fazla bellek aldığından, int dizi oluşturmak için IntStream.builder () kullanmayı tercih ederim (LongStream ve DoubleStream oluşturucularını da kullanabilirsiniz).

Misal:

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

Not: Java 8'den beri mevcuttur.


0

Bir şeyler yapabilirsin

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

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

    return personsArrayNew;

}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.