Java動的配列サイズ?


106

私はクラス-xClassを持っています。これをxClassの配列にロードしたいので、宣言を行います。

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

ただし、10が必要かどうかはわかりません。そのためには、8か12、またはその他の数が必要になる場合があります。実行時までわかりません。配列の要素数をその場で変更できますか?もしそうなら、どうですか?


質問のフォーマットを修正しました。必要に応じて、タイトルだけを記述できます。そしてstackoverflowへようこそ!:D
ゴードングスタフソン

回答:


164

いいえ、一度作成した配列のサイズを変更することはできません。必要以上に大きいサイズを割り当てるか、サイズを大きくするために再割り当てしなければならないオーバーヘッドを受け入れる必要があります。その場合、新しいものを割り当て、データを古いものから新しいものにコピーする必要があります。

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;

この状況に陥った場合は、代わりにJavaコレクションを使用することを強くお勧めします。特に、ArrayList基本的に配列をラップし、必要に応じて配列を拡張するためのロジックを処理します。

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

ArrayListとにかく、いくつかの理由から、アレイは一般にアレイの望ましいソリューションです。1つには、配列は変更可能です。これを行うクラスがある場合:

class Myclass {
    private int[] items;

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

呼び出し元がプライベートデータメンバーを変更できるため、あらゆる種類の防御コピーにつながる問題が発生しました。これをリストバージョンと比較します。

class Myclass {
    private List<Integer> items;

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

1
Listはインターフェースで、ArrayListは実装です。それをArrayListとして作成し、それをリストとして参照する(後で変更できるようにする)ことが正しいです。
CBGraham 2018

26

Javaでは配列の長さが固定されています。

リストを使用して値を保持し、toArray必要に応じてメソッドを呼び出すことができます。次のサンプルを参照してください。

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

他の人が言ったように、既存のJava配列のサイズを変更することはできません。

ArrayListは、標準のJavaが動的サイズの配列に最も近いものです。ただし、ArrayList(実際にはListインターフェース)には、「配列のように」ではないものがあります。例えば:

  • を使用[ ... ]してリストのインデックスを作成することはできません。メソッドget(int)set(int, E)メソッドを使用する必要があります。
  • ArrayListはゼロ要素で作成されます。20個の要素を持つArrayListを単純に作成してから呼び出すことはできませんset(15, foo)
  • ArrayListのサイズを直接変更することはできません。さまざまなadd、メソッドを使用して間接的にinsert行いremoveます。

より配列のようなものが必要な場合は、独自のAPIを設計する必要があります。(多分誰かが既存のサードパーティのライブラリを利用することができます...私はGoogleを使用して2分の「研究」をするものを見つけることができませんでした:-))

初期化するときに大きくなる配列だけが本当に必要な場合、解決策は次のようなものです。

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

要素の数は、作成時に任意に設定します。

xClass[] mysclass = new xClass[n];

次に、ループ内の要素を初期化できます。これがあなたが必要としていることだと思います。

作成後に配列に要素を追加または削除する必要がある場合は、を使用する必要がありますArrayList


6

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() メソッドには、配列の長さが動的に増加する問題を修正するための多くのオプションがあります。

Java API


具体的には:if(i> = mysclass.length)mysclass = Arrays.copyOf(mysclass、i + 1); mysclass [i] = new MyClass();
Micha Berger

2

はい、ラップしてコレクションフレームワークを使用します。

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

次に、必要に応じてList.toArray()を使用するか、上記のリストを反復処理します。


2

他のユーザーが言うように、おそらくjava.util.Listの実装が必要です。

何らかの理由で最終的に配列が必要になった場合は、次の2つのことを行うことができます。

  • リストを使用し、myList.toArray()で配列に変換します

  • 特定のサイズの配列を使用します。サイズを増減する必要がある場合は、java.util.Arraysメソッドを使用してサイズを変更できます。

最良の解決策はあなたの問題に依存します;)


2

代わりにベクターを使用することをお勧めします。非常に使いやすく、実装のための多くの定義済みメソッドがあります。

import java.util.*;

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

要素を追加するには、以下を使用します。

v.addElement(int);

(5,2)第5ベクトルの初期サイズです。初期サイズを超えると、ベクトルは2桁大きくなります。再び超えると、再び2桁増加します。


4
特にスレッドセーフ(-ish)タイプが必要でない限り、VectorではなくArrayListを使用する必要があります。
スティーブンC

1

myclass []配列を次のように宣言する場合:

xClass myclass[] = new xClass[10]

、必要なXClass要素の数を引数として渡すだけです。その時点で、必要な数がわかりますか?配列に10個の要素があると宣言することで、10個のXClassオブジェクトを宣言するのではなく、xClass型の10個の要素を持つ配列を作成するだけです。


1

Java配列のサイズは固定です。C++の場合のように動的配列を作成することはできません。


0

最初に格納する必要がある量を取得してから、配列を初期化することをお勧めします。

たとえば、格納する必要のあるデータの数をユーザーに尋ね、それを初期化するか、格納する必要のある数のコンポーネントまたは引数をクエリします。動的配列が必要な場合はArrayList()al.add();関数を使用して追加を続け、固定配列に転送できます。

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

そうすることは冗長ですが、ちょうどあなたのアイデアを表示する、ArrayListと完全にdynamic.same、他のプリミティブデータ型とは異なり、オブジェクトを保持して操作することは非常に簡単ですが、途中から何かを削除すると、同様に簡単ですListし、Stack


0

実行時にサイズを変更できるかどうかはわかりませんが、実行時にサイズを割り当てることができます。このコードを使用してみてください:

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

これにより、実行時にxに入力された配列サイズが割り当てられます。


0

ArrayListを使用しないメソッドを次に示します。ユーザーがサイズを指定し、再帰のためのdo-whileループを追加できます。

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では、配列のサイズは常に固定長ですが、実行時に配列のサイズを動的に大きくする方法があります。

これは、最も「使用された」方法であり、好ましい方法です。

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

上記のコードでは、新しいtemp []配列を初期化し、さらにforループを使用して、tempの内容を元の配列の内容で初期化しています。stck []。次に、もう一度コピーして元のサイズに戻し、新しいSIZEの新しい配列を提供します。

forループを繰り返し使用して配列を再初期化するため、CPUオーバーヘッドが生成されることは間違いありません。ただし、それをコードで使用して実装することはできます。可変長のデータをメモリに動的に格納する場合は、ベストプラクティスとして、配列の代わりに「リンクリスト」を使用します。

これは、実行時に配列サイズを増やす動的スタックに基づくリアルタイムの例です

ファイル名: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();
}

}

ファイル名:Exec.java
(メインクラスあり)

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

}

}

これでクエリが解決することを願っています。


0

はい、このようにできます。

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は大量のメモリを使用するため、int配列の作成にはIntStream.builder()を使用することをお勧めします(LongStreamおよびDoubleStreamビルダーも使用できます)。

例:

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

注:Java 8以降で使用可能です。


0

あなたは何かをすることができます

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

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

    return personsArrayNew;

}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.