Java动态数组大小?


106

我有一个类-xClass,我想将其加载到xClass数组中,所以我声明了:

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

但是,我不知道是否需要10。为此,我可能需要8或12或任何其他数字。我要等到运行时才能知道。我可以即时更改数组中的元素数量吗?如果是这样,怎么办?


我已修复问题的格式,如果需要,您可以只提供标题,只是描述性的。欢迎来到stackoverflow!:D
Gordon Gustafson,2009年

Answers:


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,出于多种原因,无论如何,对于数组来说,a是一个更好的解决方案。一方面,数组是可变的。如果您有这样做的班级:

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

在java中,数组长度是固定的。

您可以使用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)方法。
  • 使用零个元素创建一个ArrayList。您不能简单地创建一个包含20个元素的ArrayList,然后调用set(15, foo)
  • 您不能直接更改ArrayList的大小。你这样做间接使用不同的addinsertremove方法。

如果您想要更类似于数组的内容,则需要设计自己的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

是的,将其包装并使用Collections框架。

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

然后在必要时使用List.toArray(),或仅迭代所述List。


2

正如其他用户所说,您可能需要java.util.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)类型,否则应使用ArrayList而不是Vector。
史蒂芬·C

1

在将myclass []数组声明为的位置:

xClass myclass[] = new xClass[10]

,只需将所需的XClass元素数量作为参数传递。到那时,您知道需要多少吗?通过将数组声明为包含10个元素,您无需声明10个XClass对象,而只是创建一个包含10个类型为xClass的元素的数组。


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与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

在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占用大量内存,因此我更喜欢使用IntStream.builder()创建int数组(也可以使用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;

}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.