Kích thước mảng động Java?


106

Tôi có một lớp - xClass, mà tôi muốn tải vào một mảng xClass nên tôi khai báo:

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

Tuy nhiên, tôi không biết liệu mình có cần số 10. Tôi có thể cần 8 hoặc 12 hoặc bất kỳ số nào khác cho vấn đề đó. Tôi sẽ không biết cho đến khi thời gian chạy. Tôi có thể thay đổi nhanh số lượng phần tử trong mảng không? Nếu vậy, làm thế nào?


Tôi đã cố định định dạng của câu hỏi, bạn có thể chỉ tiêu đề nếu bạn muốn, chỉ cần mô tả. và chào mừng bạn đến với stackoverflow! : D
Gordon Gustafson 30/10/09

Câu trả lời:


164

Không, bạn không thể thay đổi kích thước của một mảng sau khi được tạo. Bạn phải phân bổ nó lớn hơn bạn nghĩ bạn sẽ cần hoặc chấp nhận chi phí phải phân bổ lại nó cần để phát triển về quy mô. Khi nó xảy ra, bạn sẽ phải cấp phát một cái mới và sao chép dữ liệu từ cái cũ sang cái mới:

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;

Nếu bạn thấy mình trong tình huống này, tôi thực sự khuyên bạn nên sử dụng Bộ sưu tập Java thay thế. Về ArrayListcơ bản, về cơ bản, bao bọc một mảng và xử lý logic để phát triển mảng theo yêu cầu:

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

Nói chung an ArrayListvẫn là một giải pháp thích hợp hơn cho một mảng vì một số lý do. Đối với một điều, các mảng có thể thay đổi. Nếu bạn có một lớp học làm điều này:

class Myclass {
    private int[] items;

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

bạn đã tạo ra sự cố vì người gọi có thể thay đổi thành viên dữ liệu cá nhân của bạn, dẫn đến tất cả các loại sao chép phòng thủ. So sánh phiên bản này với phiên bản Danh sách:

class Myclass {
    private List<Integer> items;

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

1
Danh sách là giao diện và ArrayList là phần thực hiện. Tạo nó dưới dạng ArrayList nhưng gọi nó là Danh sách (để nó có thể thay đổi sau này) là đúng.
CBGraham

26

Trong java độ dài mảng là cố định.

Bạn có thể sử dụng Danh sách để giữ các giá trị và gọi toArrayphương thức nếu cần Xem mẫu sau:

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

Như những người khác đã nói, bạn không thể thay đổi kích thước của một mảng Java hiện có.

ArrayList là mảng gần nhất mà Java tiêu chuẩn có đối với một mảng có kích thước động. Tuy nhiên, có một số điều về ArrayList (thực chất là giao diện List) không phải là "mảng như". Ví dụ:

  • Bạn không thể sử dụng [ ... ]để lập chỉ mục một danh sách. Bạn phải sử dụng các phương thức get(int)set(int, E).
  • ArrayList được tạo không có phần tử nào. Bạn không thể đơn giản tạo một ArrayList với 20 phần tử và sau đó gọi set(15, foo).
  • Bạn không thể thay đổi trực tiếp kích thước của ArrayList. Bạn làm điều đó một cách gián tiếp bằng cách sử dụng khác nhau add, insertremovephương pháp.

Nếu bạn muốn thứ gì đó giống mảng hơn, bạn sẽ cần thiết kế API của riêng mình. (Có thể ai đó có thể gọi đến thư viện bên thứ ba hiện có ... Tôi không thể tìm thấy thư viện nào có "nghiên cứu" trong 2 phút bằng Google :-))

Nếu bạn chỉ thực sự cần một mảng phát triển khi bạn đang khởi tạo nó , thì giải pháp là như thế này.

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

Bạn đặt số lượng phần tử thành bất kỳ thứ gì bạn muốn tại thời điểm bạn tạo nó:

xClass[] mysclass = new xClass[n];

Sau đó, bạn có thể khởi tạo các phần tử trong một vòng lặp. Tôi đoán rằng đây là những gì bạn cần.

Nếu bạn cần thêm hoặc xóa các phần tử vào mảng sau khi bạn tạo nó, thì bạn sẽ phải sử dụng một ArrayList.


6

Bạn có thể sử dụng 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() phương pháp có nhiều tùy chọn để khắc phục sự cố với độ dài Mảng tăng động.

API Java


Cụ thể: if (i> = mysclass.length) mysclass = Arrays.copyOf (mysclass, i + 1); mysclass [i] = new MyClass ();
Micha Berger

2

Có, bọc nó lại và sử dụng khung Bộ sưu tập.

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

Sau đó, sử dụng List.toArray () khi cần thiết hoặc chỉ cần lặp lại Danh sách đã nói.


2

Như những người dùng khác nói, bạn có thể cần triển khai java.util.List.

Nếu vì lý do nào đó, cuối cùng bạn cần một mảng, bạn có thể làm hai việc:

  • Sử dụng một Danh sách và sau đó chuyển đổi nó thành một mảng với myList.toArray ()

  • Sử dụng một mảng có kích thước nhất định. Nếu bạn cần kích thước lớn hơn hoặc nhỏ hơn, bạn có thể sửa đổi nó bằng các phương thức java.util.Arrays.

Giải pháp tốt nhất sẽ phụ thuộc vào vấn đề của bạn;)


2

Tôi khuyên bạn nên sử dụng vectơ để thay thế. Rất dễ sử dụng và có nhiều phương pháp được xác định trước để thực hiện.

import java.util.*;

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

để thêm một phần tử chỉ cần sử dụng:

v.addElement(int);

Trong (5,2) , 5 đầu tiên là kích thước ban đầu của vectơ. Nếu bạn vượt quá kích thước ban đầu, vectơ sẽ phát triển thêm 2 vị trí. Nếu nó vượt quá một lần nữa, sau đó nó sẽ lại tăng thêm 2 bậc và cứ tiếp tục như vậy.


4
Trừ khi bạn đặc biệt cần kiểu an toàn cho luồng (-ish), bạn nên sử dụng ArrayList hơn là Vector.
Stephen C

1

Nơi bạn khai báo mảng myclass [] là:

xClass myclass[] = new xClass[10]

, chỉ cần chuyển vào làm đối số số phần tử XClass bạn sẽ cần. Tại thời điểm đó, bạn có biết bạn sẽ cần bao nhiêu? Bằng cách khai báo mảng là có 10 phần tử, bạn không khai báo 10 đối tượng XClass, bạn chỉ cần tạo một mảng có 10 phần tử kiểu xClass.


1

Kích thước Mảng trong Java là cố định, Bạn không thể tạo Mảng động như trong C ++.


0

Một phương pháp hay là lấy số lượng bạn cần lưu trữ trước rồi khởi tạo mảng.

ví dụ: bạn sẽ hỏi người dùng có bao nhiêu dữ liệu anh ta cần lưu trữ và sau đó khởi tạo nó, hoặc truy vấn thành phần hoặc đối số về số lượng bạn cần lưu trữ. nếu bạn muốn một mảng động, bạn có thể sử dụng ArrayList()và sử dụng al.add();hàm để tiếp tục thêm, sau đó bạn có thể chuyển nó sang một mảng cố định.

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

làm như vậy là thừa nhưng chỉ để cho bạn thấy ý tưởng, ArrayListcó thể chứa các đối tượng không giống như các kiểu dữ liệu nguyên thủy khác và rất dễ thao tác, xóa bất kỳ thứ gì ở giữa cũng dễ dàng, hoàn toàn động. tên với ListStack


0

Tôi không biết liệu bạn có thể thay đổi kích thước trong thời gian chạy hay không nhưng bạn có thể phân bổ kích thước trong thời gian chạy. Hãy thử sử dụng mã này:

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

điều này chỉ định kích thước mảng của bạn là kích thước được nhập tại thời điểm chạy thành x.


0

Đây là một phương thức không sử dụng ArrayList. Người dùng chỉ định kích thước và bạn có thể thêm vòng lặp do-while cho đệ quy.

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

Trong Java, kích thước mảng luôn có độ dài cố định nhưng có cách để bạn có thể tự động tăng kích thước của mảng trong thời gian chạy chính nó

Đây là cách được "sử dụng" cũng như được ưa thích nhất-

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

Trong đoạn mã trên, chúng ta đang khởi tạo một mảng temp [] mới và tiếp tục sử dụng vòng lặp for để khởi tạo nội dung của tạm thời với nội dung của mảng ban đầu tức là. stck []. Và sau đó lại sao chép nó trở lại bản gốc, cho chúng ta một mảng KÍCH THƯỚC mới.

Không nghi ngờ gì nữa, nó tạo ra Chi phí CPU do khởi động lại một mảng bằng cách sử dụng vòng lặp for lặp đi lặp lại. Nhưng bạn vẫn có thể sử dụng và triển khai nó trong mã của mình. Đối với phương pháp hay nhất, hãy sử dụng "Danh sách được liên kết" thay vì Mảng, nếu bạn muốn dữ liệu được lưu trữ động trong bộ nhớ, có độ dài thay đổi.

Đây là một ví dụ trong thời gian thực dựa trên ngăn xếp động để TĂNG KÍCH THƯỚC ĐẾN TẠI Thời gian chạy

Tên tệp: 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();
}

}

Tên tệp: Exec.java
(với lớp chính)

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

}

}

Hy vọng điều này giải quyết được thắc mắc của bạn.


0

Có, chúng tôi có thể làm theo cách này.

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

Vì ArrayList chiếm nhiều bộ nhớ khi tôi cần mảng kiểu nguyên thủy, nên tôi thích sử dụng IntStream.builder () để tạo mảng int (Bạn cũng có thể sử dụng các trình tạo LongStream và DoubleStream).

Thí dụ:

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

Lưu ý: có sẵn kể từ Java 8.


0

Bạn có thể làm một số điều

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

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

    return personsArrayNew;

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.