2011-02-02 35 views
30

Làm cách nào để xóa một mục khỏi một mảng và sau đó thay đổi kích cỡ mảng thành kích thước nhỏ hơn? Tương tự, làm cách nào để tăng dung lượng nếu tôi cần thêm một mục khác?Xóa mục khỏi mảng và thu hẹp mảng

+0

là 'mảng' các đòi hỏi cấu trúc dữ liệu đối với trường hợp sử dụng của bạn? Có vẻ như bạn đang sử dụng búa sai –

Trả lời

0

Mảng có kích thước cố định, bạn không thể thay đổi kích thước chúng sau khi tạo chúng. Bạn có thể loại bỏ một mục hiện có bằng cách thiết lập nó để null:

objects[4] = null; 

Nhưng bạn sẽ không thể xóa toàn bộ khe tắt mảng và giảm kích thước của nó bằng 1.

Nếu bạn cần một động mảng có kích thước, bạn có thể sử dụng ArrayList. Với nó, bạn có thể add()remove() đối tượng và nó sẽ phát triển và thu nhỏ khi cần thiết.

+0

Vì vậy, tôi có thể tạo một mảng mới mà không có mục mà tôi muốn xóa không? – Joe

+0

@Joe: Đó cũng là một lựa chọn có thể; hãy xem các câu trả lời khác. – BoltClock

15

Bạn không thể thay đổi kích thước mảng, mỗi gia nhập, nhưng bạn có thể tạo ra một mảng mới và hiệu quả sao chép các yếu tố từ mảng cũ sang mảng mới sử dụng một số chức năng hữu ích như thế này:

public static int[] removeElement(int[] original, int element){ 
    int[] n = new int[original.length - 1]; 
    System.arraycopy(original, 0, n, 0, element); 
    System.arraycopy(original, element+1, n, element, original.length - element-1); 
    return n; 
} 

Một cách tiếp cận tốt hơn, tuy nhiên, sẽ sử dụng một ArrayList (hoặc cấu trúc Danh sách tương tự) để lưu trữ dữ liệu của bạn và sau đó sử dụng các phương thức của nó để loại bỏ các phần tử khi cần thiết.

+1

Có lỗi trong mã này, điều này sẽ khiến mã này luôn ném NPE. Tôi đã chỉnh sửa câu trả lời với bản sửa lỗi. – Joel

+0

Gọi phương thức System.arraycopy đầu tiên là không cần thiết. – Stuart

1
object[] newarray = new object[oldarray.Length-1]; 

for(int x=0; x < array.Length; x++) 
{ 
    if(!(array[x] == value_of_array_to_delete)) 
    // if(!(x == array_index_to_delete)) 
    { 
    newarray[x] = oldarray[x]; 
    } 
} 

Không có cách nào để giảm kích thước mảng sau khi được tạo, nhưng bạn có thể sao chép nội dung sang mảng khác có kích thước nhỏ hơn.

+0

Điều gì sẽ xảy ra nếu tôi chỉ muốn bỏ qua byte cuối cùng của một mảng 640 byte ... – aProgrammer

+0

Sau đó, instantiation của bạn sẽ là 'object [] new array = new object [oldarray.Length-2];' vòng lặp for sẽ xử lý gia số. – Mike

+0

Tôi có nghĩa là .. Chúng ta cần phải tạo ra một mảng mới ngay cả khi chúng ta chỉ muốn bỏ qua một byte .. Chúng ta có thể thu nhỏ mảng không? – aProgrammer

22

Kích thước của một mảng Java là cố định khi bạn phân bổ nó, và không thể thay đổi.

  • Nếu bạn muốn "phát triển" hoặc "thu hẹp" mảng hiện có, bạn phải phân bổ mảng mới có kích thước phù hợp và sao chép phần tử mảng; ví dụ. sử dụng System.arraycopy(...) hoặc Arrays.copyOf(...). Một vòng lặp bản sao hoạt động như là tốt, mặc dù có vẻ hơi clunky ... IMO.

  • Nếu bạn muốn "xóa" mục hoặc mục từ một mảng (theo đúng nghĩa ... không chỉ thay thế chúng bằng null), bạn cần phân bổ một mảng nhỏ mới và sao chép trên các phần tử bạn muốn giữ lại.

Có lựa chọn thay thế bằng hình thức thư viện của bên thứ 3 (ví dụ như Apache Commons ArrayUtils), nhưng bạn có thể muốn xem xét liệu nó là giá trị thêm một sự phụ thuộc thư viện chỉ vì lợi ích của một phương pháp mà bạn có thể tự thực hiện với 5-10 dòng mã.


Nó là tốt hơn (ví dụ đơn giản ... và trong nhiều trường hợp, hiệu quả hơn) sử dụng một lớp List thay vì một mảng. Điều này sẽ chăm sóc (ít nhất) phát triển lưu trữ sao lưu. Và có các hoạt động xử lý việc chèn và xóa các phần tử ở bất kỳ đâu trong danh sách.

Ví dụ: lớp ArrayList sử dụng mảng làm bản sao lưu và tự động phát triển mảng theo yêu cầu. Nó không tự động giảm kích thước của mảng sao lưu, nhưng bạn có thể yêu cầu nó làm điều này bằng cách sử dụng phương thức trimToSize(); ví dụ.

ArrayList l = ... 
l.remove(21); 
l.trimToSize(); // Only do this if you really have to. 

1 - Tôi nói đó là "hiệu quả hơn trong nhiều trường hợp" vì ArrayList sử dụng một đơn giản "gấp đôi so với kích thước" chiến lược khi cần thiết để phát triển mảng ủng hộ. Điều này có nghĩa rằng nếu phát triển danh sách bằng cách liên tục thêm vào nó, mỗi phần tử sẽ được sao chép trung bình thêm một lần nữa. Ngược lại, nếu bạn đã làm điều này với một mảng bạn sẽ kết thúc sao chép mỗi phần tử mảng gần N/2 lần trung bình.

0

mà không sử dụng phương pháp System.arraycopy bạn có thể xóa một phần tử từ một mảng như sau

int i = 0; 
    int x = 0; 
    while(i < oldArray.length){ 
     if(oldArray[i] == 3)i++; 

     intArray[x] = oldArray[i]; 
     i++; 
     x++; 
    } 

nơi 3 là giá trị mà bạn muốn loại bỏ.

+0

Điều này chưa hoàn chỉnh. Và không thực sự trả lời câu hỏi. –

11

Sử dụng ArrayUtils.removeElement(Object[],Object) từ org.apache.commons.lang là cách dễ nhất để thực hiện việc này.

int[] numbers = {1,2,3,4,5,6,7}; 
//removing number 1 
numbers =(int[])ArrayUtils.removeElement(numbers, 1); 
+2

Điều này không thực sự thay đổi kích cỡ mảng. Nó tạo ra một cái mới. Nhưng không có cách nào khác, vì kích thước của mảng không thể thay đổi được. – MrSmith42

+0

là sản phẩm tốt nhất. – Simmant

2

Tôi đã tạo hàm hoặc lớp này. Im kinda mới nhưng bạn của tôi cũng cần điều này vì vậy tôi đã tạo điều này:

public String[] name(int index, String[] z){ 
    if(index > z.length){ 
     return z; 
    } else { 
     String[] returnThis = new String[z.length - 1]; 
     int newIndex = 0; 
     for(int i = 0; i < z.length; i++){ 
      if(i != index){ 
       returnThis[newIndex] = z[i]; 
       newIndex++; 
      } 
     } 
     return returnThis; 
    } 
} 

Vì nó rất vui, tôi nghĩ tôi sẽ đăng ở đây.

2

Vì mảng có kích thước cố định được cấp phát khi được tạo, tùy chọn duy nhất của bạn là tạo mảng mới mà không có phần tử bạn muốn xóa.

Nếu phần tử bạn muốn loại bỏ là mục mảng cuối cùng, điều này trở nên dễ thực hiện sử dụng Arrays.copy:

int a[] = { 1, 2, 3}; 
a = Arrays.copyOf(a, 2); 

Sau khi chạy đoạn mã trên, bây giờ là một sẽ trỏ đến một mảng mới chỉ chứa 1, Nếu không, nếu phần tử bạn muốn xóa không phải là phần tử cuối cùng, bạn cần phải tạo một mảng mới ở kích thước-1 và sao chép tất cả các mục vào nó trừ phần bạn muốn xóa.

Cách tiếp cận ở trên không hiệu quả. Nếu bạn cần quản lý danh sách các mục có thể thay đổi trong bộ nhớ, hãy sử dụng Danh sách tốt hơn. Cụ thể, LinkedList sẽ xóa một mục khỏi danh sách trong O(1) (nhanh nhất về mặt lý thuyết).

+0

Đối với tôi giải pháp làm việc tốt nhất và ngắn nhất để cắt ngắn một mảng. Cảm ơn! – Ruwen

-1

Bạn luôn có thể mở rộng một mảng chỉ bằng cách tăng kích thước của nó trong khi tạo mảng hoặc bạn cũng có thể thay đổi kích thước sau khi tạo, nhưng để thu nhỏ hoặc xóa các phần tử. Giải pháp thay thế mà không tạo mảng mới, có thể là:

package sample; 

public class Delete { 
    int i; 
    int h=0; 
    int n=10; 
    int[] a; 
    public Delete() 
    { 
    a = new int[10]; 
    a[0]=-1; 
    a[1]=-1; 
    a[2]=-1; 
    a[3]=10; 
    a[4]=20; 
    a[5]=30; 
    a[6]=40; 
    a[7]=50; 
    a[8]=60; 
    a[9]=70; 
    } 
    public void shrinkArray() 
    { 
    for(i=0;i<n;i++) 
      { 
       if(a[i]==-1) 
        h++; 
       else 
        break; 
      } 
      while(h>0) 
       { 
        for(i=h;i<n;i++) 
        { 
         a[i-1]=a[i]; 
        } 
        h--; 
        n--; 
       } 
      System.out.println(n); 
    } 
    public void display() 
    { 
     for(i=0;i<n;i++) 
     { 
      System.out.println(a[i]); 
     } 
    } 

    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     Delete obj = new Delete(); 
     obj.shrinkArray(); 
     obj.display(); 

    } 

} 

Hãy bình luận cho bất kỳ sai lầm nào !!

+0

Điều này không thay đổi kích cỡ mảng theo yêu cầu. –

-2

Không sử dụng bất kỳ chức năng trước khi được xác định cũng như hiệu quả: --- >>

public static void Delete(int d , int[] array) 
{  
    Scanner in = new Scanner (System.in); 

    int i , size = array.length; 

    System.out.println("ENTER THE VALUE TO DELETE? "); 

    d = in.nextInt(); 

     for (i=0;i< size;i++) 
     { 
       if (array[i] == d) 
         { 


          int[] arr3 =new int[size-1]; 
          int[] arr4 = new int[i]; 
          int[] arr5 = new int[size-i-1]; 

            for (int a =0 ;a<i;a++) 
            { 
             arr4[a]=array[a]; 
             arr3[a] = arr4[a]; 
            } 
            for (int a =i ;a<size-1;a++) 
            { 
             arr5[a-i] = array[a+1]; 
             arr3[a] = arr5[a-i]; 

            } 


       System.out.println(Arrays.toString(arr3)); 

         } 
       else System.out.println("************");  


     } 

} 
+0

Điều này không thay đổi kích thước mảng theo yêu cầu. –

Các vấn đề liên quan