ขนาดอาร์เรย์ไดนามิกของ Java?


106

ฉันมีคลาส - xClass ที่ฉันต้องการโหลดลงในอาร์เรย์ของ xClass ดังนั้นฉันจึงประกาศ:

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

อย่างไรก็ตามฉันไม่รู้ว่าฉันต้องการ 10 หรือไม่ฉันอาจต้องการ 8 หรือ 12 หรือหมายเลขอื่น ๆ สำหรับเรื่องนั้น ฉันจะไม่รู้จนกว่าจะรันไทม์ ฉันสามารถเปลี่ยนจำนวนองค์ประกอบในอาร์เรย์ได้ทันทีหรือไม่? ถ้าเป็นอย่างไร


ฉันแก้ไขการจัดรูปแบบของคำถามแล้วคุณสามารถตั้งชื่อได้หากต้องการเพียงแค่บรรยาย และยินดีต้อนรับสู่ stackoverflow! : D
Gordon Gustafson

คำตอบ:


166

ไม่คุณไม่สามารถเปลี่ยนขนาดของอาร์เรย์เมื่อสร้างแล้ว คุณต้องจัดสรรให้ใหญ่กว่าที่คุณคิดว่าจะต้องใช้หรือยอมรับค่าใช้จ่ายในการจัดสรรใหม่เพื่อให้มีขนาดใหญ่ขึ้น เมื่อใดคุณจะต้องจัดสรรใหม่และคัดลอกข้อมูลจากเก่าไปใหม่:

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

โดยทั่วไปแล้ว an 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

ในความยาวอาร์เรย์ 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 (จริงๆแล้วคืออินเทอร์เฟซรายการ) ที่ไม่ใช่ "array like" ตัวอย่างเช่น:

  • คุณไม่สามารถใช้[ ... ]เพื่อจัดทำดัชนีรายการ คุณต้องใช้get(int)และset(int, E)วิธีการ
  • ArrayList ถูกสร้างขึ้นโดยมีองค์ประกอบเป็นศูนย์ คุณไม่สามารถสร้าง ArrayList ด้วยองค์ประกอบ 20 รายการได้ง่ายๆแล้วโทร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] = MyClass ใหม่ ();
Micha Berger

2

ใช่ห่อและใช้กรอบงานคอลเล็กชัน

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

จากนั้นใช้ List.toArray () เมื่อจำเป็นหรือเพียงแค่ทำซ้ำในรายการดังกล่าว


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
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สามารถถือวัตถุที่แตกต่างจากประเภทข้อมูลดั้งเดิมอื่น ๆ และจัดการได้ง่ายมากการลบอะไรออกจากตรงกลางก็ทำได้ง่ายเช่นกันไดนามิกอย่างสมบูรณ์เหมือนกันกับ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 loop เพื่อเริ่มต้นเนื้อหาของ temp ด้วยเนื้อหาของอาร์เรย์ดั้งเดิมเช่น stck [] จากนั้นคัดลอกกลับไปที่ต้นฉบับอีกครั้งทำให้เรามี SIZE ใหม่

ไม่ต้องสงสัยเลยว่ามันสร้าง CPU Overhead เนื่องจากการเริ่มต้นอาร์เรย์ใหม่โดยใช้สำหรับลูปซ้ำ ๆ แต่คุณยังสามารถใช้และติดตั้งในโค้ดของคุณได้ สำหรับแนวทางปฏิบัติที่ดีที่สุดให้ใช้ "รายการที่เชื่อมโยง" แทนอาร์เรย์หากคุณต้องการให้จัดเก็บข้อมูลแบบไดนามิกในหน่วยความจำโดยมีความยาวผันแปรได้

นี่คือตัวอย่างแบบเรียลไทม์ที่อิงตาม Dynamic Stacks เพื่อเพิ่มขนาดอาร์เรย์ในเวลารัน

ชื่อไฟล์: 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;

}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.