我有一个类-xClass,我想将其加载到xClass数组中,因此需要声明:

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


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

评论

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

#1 楼

不,一旦创建,就无法更改数组的大小。您要么必须分配比您认为需要的更大的大小,要么接受必须重新分配它的开销,这需要增加它的大小。在这种情况下,您将不得不分配一个新数据并将其从旧数据复制到新数据:

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;


如果您遇到这种情况,我会d强烈建议改为使用Java集合。特别是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);
    }
}


评论


List是接口,而ArrayList是实现。将其创建为ArrayList但将其引用为List(以便以后可以更改)是正确的。

– CBGraham
18-09-24在16:25

#2 楼

在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 {}


#3 楼

正如其他人所说,您不能更改现有Java数组的大小。

ArrayList是标准Java与动态大小的数组最接近的数组。但是,有些关于ArrayList的东西(实际上是List接口)不是“类似于数组”。例如:


您不能使用[ ... ]为列表建立索引。您必须使用get(int)set(int, E)方法。
使用零个元素创建ArrayList。您不能简单地创建一个包含20个元素的ArrayList,然后调用set(15, foo)
您不能直接更改ArrayList的大小。您可以使用各种addinsertremove方法间接进行此操作。

如果您想要更类似于数组的内容,则需要设计自己的API。 (也许有人可以使用现有的第三方库...在2分钟的时间内,我无法使用Google进行“研究” :-))

如果您只需要一个可以增长的数组初始化时,解决方案是这样的。

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


#4 楼

您可以在创建元素时将元素的数量设置为所需的任何内容:

xClass[] mysclass = new xClass[n];


然后您可以循环初始化元素。我猜这就是您所需要的。

如果在创建数组后需要在数组中添加或删除元素,则必须使用ArrayList

#5 楼

您可以使用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());


#6 楼

就像其他用户说的那样,您可能需要java.util.List的实现。

如果出于某种原因最终需要一个数组,则可以做两件事:


使用列表,然后使用myList.toArray()将其转换为数组。使用特定大小的数组。如果需要更多或更少的大小,则可以使用java.util.Arrays方法进行修改。

#7 楼

Arrays.copyOf()方法有很多选项可以解决动态增加数组长度的问题。

Java API

评论


具体来说:if(i> = mysclass.length)mysclass = Arrays.copyOf(mysclass,i + 1); mysclass [i] = new MyClass();

– Micha Berger
17年8月30日在20:39



#8 楼

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

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


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

#9 楼

我建议改用向量。非常易于使用,并具有许多预定义的实现方法。

import java.util.*;

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


只需使用以下元素即可添加元素:

v.addElement(int);


在(5,2)中,前5个是向量的初始大小。如果超过初始大小,向量将增加2个位置。如果再次超过,则它将再次增加2位,依此类推。

评论


除非您特别需要线程安全(-ish)类型,否则应使用ArrayList而不是Vector。

– Stephen C
2012年11月27日13:07

#10 楼

在将myclass []数组声明为:

xClass myclass[] = new xClass[10]


的地方,只需将所需的XClass元素数量作为参数传入即可。到那时,您知道需要多少吗?通过将数组声明为包含10个元素,您并没有声明10个XClass对象,您只是在创建一个包含10个类型为xClass的元素的数组。

#11 楼

Java数组大小是固定的,您不能像在C ++中那样创建动态数组。

#12 楼

最好先获取要存储的数量,然后初始化数组。

,例如,您将询问用户需要存储多少数据,然后对其进行初始化,或者查询组件或需要存储多少个参数。
如果要动态数组,可以使用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可以容纳对象,这与其他原始数据类型不同,并且非常易于操作,从中间删除任何内容也很容易,而且完全动态。与ListStack相同

#13 楼

我不知道是否可以在运行时更改大小,但是可以在运行时分配大小。尝试使用以下代码:

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中输入的大小。

#14 楼

这是一种不使用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);
        }
    }


#15 楼

在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的内容来初始化temp的内容。原始数组即stck []。然后再次将其复制回原始副本,从而为我们提供了一个新的新SIZE数组。
为了最佳实践,如果希望将数据动态存储在可变长度的内存中,请使用“链接列表”而不是数组。

这是一个基于动态堆栈的实时示例,可以在运行时增加阵列大小

文件名: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);

}

}


希望这可以解决您的查询。

#16 楼

是的,我们可以这样做。

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


}


#17 楼

因为当我需要基本类型数组时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起可用。

#18 楼

您可以做一些事情

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

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

    return personsArrayNew;

}