자바 동적 배열 크기?


106

xClass의 배열에로드하려는 클래스-xClass가 있으므로 선언합니다.

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

그러나 10 개가 필요한지 모르겠습니다. 그 문제에 대해 8 개 또는 12 개 또는 다른 번호가 필요할 수 있습니다. 런타임까지 알 수 없습니다. 배열의 요소 수를 즉시 변경할 수 있습니까? 그렇다면 어떻게?


질문의 형식을 수정했습니다. 원하는 경우 제목 만 입력 할 수 있습니다. 그리고 stackoverflow에 오신 것을 환영합니다! : D
Gordon Gustafson

답변:


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 Collections를 대신 사용하는 것이 좋습니다. 특히 ArrayList기본적으로 배열을 래핑하고 필요에 따라 배열을 늘리는 논리를 처리합니다.

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

일반적으로는 ArrayList여러 가지 이유로 배열에 대한 바람직한 솔루션입니다. 우선, 배열은 변경 가능합니다. 이 작업을 수행하는 클래스가있는 경우 :

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로 생성하지만 List로 참조하는 것이 맞습니다 (나중에 변경할 수 있음).
CBGraham

26

자바에서는 배열 길이가 고정되어 있습니다.

List를 사용하여 값을 보유하고 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)메서드 를 사용해야합니다 .
  • 0 요소로 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() 메서드에는 배열 길이가 동적으로 증가하는 문제를 해결하는 많은 옵션이 있습니다.

자바 API


구체적으로 말하자면 : if (i> = mysclass.length) mysclass = Arrays.copyOf (mysclass, i + 1); mysclass [i] = new MyClass ();
Micha Berger

2

예, 래핑하고 Collections 프레임 워크를 사용합니다.

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

그런 다음 필요한 경우 List.toArray ()를 사용하거나 해당 List를 반복합니다.


2

다른 사용자가 말했듯이 java.util.List의 구현이 필요할 수 있습니다.

어떤 이유로 마침내 배열이 필요한 경우 두 가지 작업을 수행 할 수 있습니다.

  • List를 사용한 다음 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를 사용해야합니다.
Stephen C

1

myclass [] 배열을 다음과 같이 선언합니다.

xClass myclass[] = new xClass[10]

, 필요한 XClass 요소의 수를 인수로 전달하기 만하면됩니다. 그 시점에서 얼마나 많은 것이 필요할지 알고 있습니까? 배열에 10 개의 요소가있는 것으로 선언하면 10 개의 XClass 객체를 선언하는 것이 아니라 단순히 xClass 유형의 10 개 요소로 배열을 만드는 것입니다.


1

Java Array 크기는 고정되어 있으므로 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입니다 중간에서 아무것도 제거, 매우 쉽게 조작 할 수있는 수 ListStack


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

자바에서 배열 크기는 항상 고정 길이이지만 런타임 자체에서 배열 크기를 동적으로 늘릴 수있는 방법이 있습니다.

이것이 가장 "사용되는"방법이자 선호하는 방법입니다.

    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 []. 그런 다음 다시 원본에 다시 복사하여 새로운 크기의 새로운 배열을 제공합니다.

반복적으로 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.