簡體   English   中英

如何從 Java 中的數組中刪除對象?

[英]How do I remove objects from an array in Java?

給定一個包含n 個對象的數組,假設它是一個字符串數組,它具有以下值:

foo[0] = "a";
foo[1] = "cc";
foo[2] = "a";
foo[3] = "dd";

我該怎么做才能刪除/刪除數組中等於“a”的所有字符串/對象?

[如果你想要一些現成的代碼,請滾動到我的“Edit3”(剪切后)。 其余的留在這里供后代使用。]

充實 Dustman 的想法

List<String> list = new ArrayList<String>(Arrays.asList(array));
list.removeAll(Arrays.asList("a"));
array = list.toArray(array);

編輯:我現在使用Arrays.asList而不是Collections.singleton :單例僅限於一個條目,而asList方法允許您添加其他字符串以稍后過濾: Arrays.asList("a", "b", "c")

Edit2:上面的方法保留了相同的數組(所以數組仍然是相同的長度); 最后一個之后的元素設置為空。 如果您想要一個大小完全符合要求的數組,請改用:

array = list.toArray(new String[0]);

Edit3:如果您在同一個類中經常使用此代碼,您可能希望考慮將其添加到您的類中:

private static final String[] EMPTY_STRING_ARRAY = new String[0];

那么函數就變成了:

List<String> list = new ArrayList<>();
Collections.addAll(list, array);
list.removeAll(Arrays.asList("a"));
array = list.toArray(EMPTY_STRING_ARRAY);

然后,這將停止用無用的空字符串數組亂扔堆,否則每次調用函數時都會new ed。

憤世嫉俗的人的建議(見評論)也將有助於堆垃圾,為了公平起見,我應該提到它:

array = list.toArray(new String[list.size()]);

我更喜歡我的方法,因為它可能更容易得到錯誤的顯式大小(例如,在錯誤的列表上調用size() )。

Java 8 中的替代方案:

String[] filteredArray = Arrays.stream(array)
    .filter(e -> !e.equals(foo)).toArray(String[]::new);

使用Arrays.asList()從數組中Arrays.asList()一個List ,並在所有適當的元素上調用remove() 然后在“列表”上調用toArray()以再次返回數組。

性能不是很好,但是如果您正確地封裝它,您以后總是可以更快地做一些事情。

你總是可以這樣做:

int i, j;
for (i = j = 0; j < foo.length; ++j)
  if (!"a".equals(foo[j])) foo[i++] = foo[j];
foo = Arrays.copyOf(foo, i);

您可以使用外部庫:

org.apache.commons.lang.ArrayUtils.remove(java.lang.Object[] array, int index)

它在 Apache Commons Lang 項目中http://commons.apache.org/lang/

見下面的代碼

ArrayList<String> a = new ArrayList<>(Arrays.asList(strings));
a.remove(i);
strings = new String[a.size()];
a.toArray(strings);

如果您需要從數組中刪除多個元素而不將其轉換為List或創建額外的數組,您可以在 O(n) 中執行此操作,而不依賴於要刪除的項目數。

這里, a是初始數組, int... r是要刪除的元素的不同有序索引(位置):

public int removeItems(Object[] a, int... r) {
    int shift = 0;                             
    for (int i = 0; i < a.length; i++) {       
        if (shift < r.length && i == r[shift])  // i-th item needs to be removed
            shift++;                            // increment `shift`
        else 
            a[i - shift] = a[i];                // move i-th item `shift` positions left
    }
    for (int i = a.length - shift; i < a.length; i++)
        a[i] = null;                            // replace remaining items by nulls

    return a.length - shift;                    // return new "length"
}  

小測試:

String[] a = {"0", "1", "2", "3", "4"};
removeItems(a, 0, 3, 4);                     // remove 0-th, 3-rd and 4-th items
System.out.println(Arrays.asList(a));        // [1, 2, null, null, null]

在您的任務中,您可以先掃描數組以收集“a”的位置,然后調用removeItems()

這里有很多答案——我看到的問題是你沒有說你為什么使用數組而不是集合,所以讓我提出幾個原因以及哪些解決方案適用(大多數解決方案已經在其他問題中得到了回答,所以我不再贅述):

原因:您不知道收集包存在或不信任它

解決方案:使用集合。

如果您打算從中間添加/刪除,請使用 LinkedList。 如果您真的很擔心大小或經常索引到集合的中間,請使用 ArrayList。 這兩個都應該有刪除操作。

原因:您擔心大小或想要控制內存分配

解決方案:使用具有特定初始大小的 ArrayList。

ArrayList 只是一個可以擴展自身的數組,但並不總是需要這樣做。 添加/刪除項目將非常聰明,但是如果您要從中間插入/刪除很多,請使用 LinkedList。

原因:你有一個數組進來,一個數組出去——所以你想對一個數組進行操作

解決方案:將其轉換為ArrayList,刪除該項目並將其轉換回來

理由:你認為如果你自己做,你可以寫出更好的代碼

解決方案:你不能,使用數組或鏈表。

原因:這是一個課堂作業,您不被允許或由於某種原因無法訪問集合 api

假設:您需要新數組是正確的“大小”

解決方案:掃描數組中的匹配項並對其進行計數。 創建一個正確大小的新數組(原始大小 - 匹配數)。 重復使用 System.arraycopy 將您希望保留的每組項目復制到新數組中。 如果這是一個類分配並且您不能使用 System.arraycopy,只需在循環中手動一次復制它們,但永遠不要在生產代碼中這樣做,因為它會慢得多。 (這些解決方案在其他答案中都有詳細說明)

原因:你需要運行裸機

假設:您不得不必要地分配空間或花費太長時間

假設:您正在單獨跟蹤數組中使用的大小(長度),否則您必須重新分配數組以進行刪除/插入。

您可能想要這樣做的原因的一個示例:單個原語數組(假設為 int 值)占用了您 ram 的很大一部分——比如 50%! ArrayList 會強制將它們放入指向 Integer 對象的指針列表中,這些對象將使用該數量的內存的幾倍。

解決方案:迭代您的數組,每當您找到要刪除的元素(我們稱之為元素 n)時,使用 System.arraycopy 將數組的尾部復制到“已刪除”元素上(源和目標是相同的數組)--它足夠聰明以正確的方向進行復制,因此內存不會覆蓋自身:

System.arraycopy(ary, n+1, ary, n, length-n) 
 length--;

如果您一次刪除多個元素,您可能希望比這更聰明。 您只會在一個“匹配”和下一個“匹配”之間移動區域而不是整個尾部,並且一如既往地避免將任何塊移動兩次。

在最后一種情況下,您絕對必須自己完成這項工作,並且使用 System.arraycopy 確實是唯一的方法,因為它將為您的計算機體系結構選擇最佳的內存移動方式——它應該快很多倍比您自己可以合理編寫的任何代碼。

關於制作它的列表然后刪除然后返回到數組的一些事情讓我覺得是錯誤的。 還沒有測試,但我認為以下會表現得更好。 是的,我可能進行了過度的預優化。

boolean [] deleteItem = new boolean[arr.length];
int size=0;
for(int i=0;i<arr.length;i==){
   if(arr[i].equals("a")){
      deleteItem[i]=true;
   }
   else{
      deleteItem[i]=false;
      size++;
   }
}
String[] newArr=new String[size];
int index=0;
for(int i=0;i<arr.length;i++){
   if(!deleteItem[i]){
      newArr[index++]=arr[i];
   }
}

我意識到這是一個很老的帖子,但這里的一些答案幫助了我,所以這是我的 tuppence' ha'penny 的價值!

除非對ArrayList所做的更改使列表大小保持不變,否則我努力讓它工作了很長一段時間,然后才知道我正在寫回的數組需要調整大小。

如果您正在修改的ArrayList的元素比開始時多List.toArray() ,則List.toArray()行將導致異常,因此您需要List.toArray(new String[] {})List.toArray(new String[0])以創建具有新(正確)大小的數組。

現在我知道了,這聽起來很明顯。 對於開始處理新的和不熟悉的代碼結構的 Android/Java 新手來說並不那么明顯,而且從這里的一些早期帖子中並不明顯,所以只想讓其他人真正清楚這一點,因為其他人像我一樣撓了幾個小時!

初始數組

   int[] array = {5,6,51,4,3,2};

如果要刪除索引 2 的 51,請使用以下內容

 for(int i = 2; i < array.length -1; i++){
    array[i] = array[i + 1];
  }

編輯:

數組中具有空值的點已被清除。 抱歉我的評論。

原來的:

嗯……那條線

array = list.toArray(array);

將數組中已刪除元素所在的所有空白替換為null 這可能很危險,因為元素被刪除了,但數組的長度保持不變!

如果您想避免這種情況,請使用新數組作為 toArray() 的參數。 如果您不想使用 removeAll,則可以使用 Set 替代:

        String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" };

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

        Set<String> asSet = new HashSet<String>(Arrays.asList(array));
        asSet.remove("a");
        array = asSet.toArray(new String[] {});

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

給出:

[a, bc, dc, a, ef]
[dc, ef, bc]

正如 Chris Yester Young 輸出的當前接受的答案:

[a, bc, dc, a, ef]
[bc, dc, ef, null, ef]

用代碼

    String[] array = new String[] { "a", "bc" ,"dc" ,"a", "ef" };

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

    List<String> list = new ArrayList<String>(Arrays.asList(array));
    list.removeAll(Arrays.asList("a"));
    array = list.toArray(array);        

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

沒有留下任何空值。

我對這個問題的一點貢獻。

public class DeleteElementFromArray {
public static String foo[] = {"a","cc","a","dd"};
public static String search = "a";


public static void main(String[] args) {
    long stop = 0;
    long time = 0;
    long start = 0;
    System.out.println("Searched value in Array is: "+search);
    System.out.println("foo length before is: "+foo.length);
    for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);}
    System.out.println("==============================================================");
    start = System.nanoTime();
    foo = removeElementfromArray(search, foo);
    stop = System.nanoTime();
    time = stop - start;
    System.out.println("Equal search took in nano seconds = "+time);
    System.out.println("==========================================================");
    for(int i=0;i<foo.length;i++){ System.out.println("foo["+i+"] = "+foo[i]);}
}
public static String[] removeElementfromArray( String toSearchfor, String arr[] ){
     int i = 0;
     int t = 0;
     String tmp1[] = new String[arr.length];     
         for(;i<arr.length;i++){
              if(arr[i] == toSearchfor){     
              i++;
              }
             tmp1[t] = arr[i];
             t++;
     }   
     String tmp2[] = new String[arr.length-t];   
     System.arraycopy(tmp1, 0, tmp2, 0, tmp2.length);
     arr = tmp2; tmp1 = null; tmp2 = null;
    return arr;
}

}

啊,我無法讓代碼正確顯示。 對不起,我讓它工作了。 再次抱歉,我認為我沒有正確閱讀問題。

String  foo[] = {"a","cc","a","dd"},
remove = "a";
boolean gaps[] = new boolean[foo.length];
int newlength = 0;

for (int c = 0; c<foo.length; c++)
{
    if (foo[c].equals(remove))
    {
        gaps[c] = true;
        newlength++;
    }
    else 
        gaps[c] = false;

    System.out.println(foo[c]);
}

String newString[] = new String[newlength];

System.out.println("");

for (int c1=0, c2=0; c1<foo.length; c1++)
{
    if (!gaps[c1])
    {
        newString[c2] = foo[c1];
        System.out.println(newString[c2]);
        c2++;
    }
}

這取決於您所說的“刪除”是什么意思? 數組是一個固定大小的結構——你不能改變其中的元素數量。 因此,您可以 a) 創建一個新的、更短的數組,而沒有您不想要的元素,或者 b) 將您不想要的條目分配給指示其“空”狀態的內容; 如果您不使用原語,通常為 null。

在第一種情況下,從數組中創建一個列表,刪除元素,然后從列表中創建一個新數組。 如果性能很重要,則遍歷數組,將不應刪除的任何元素分配給列表,然后從列表中創建一個新數組。 在第二種情況下,只需通過並將 null 分配給數組條目。

將復制除索引為 i 的元素之外的所有元素:

if(i == 0){
                System.arraycopy(edges, 1, copyEdge, 0, edges.length -1 );
            }else{
                System.arraycopy(edges, 0, copyEdge, 0, i );
                System.arraycopy(edges, i+1, copyEdge, i, edges.length - (i+1) );
            }

如果元素的順序無關緊要。 您可以在元素 foo[x] 和 foo[0] 之間交換,然后調用 foo.drop(1)。

foo.drop(n)從數組中刪除 (n) 個第一個元素。

我想這是最簡單且資源高效的方法。

PS : indexOf可以通過多種方式實現,這是我的版本。

Integer indexOf(String[] arr, String value){
    for(Integer i = 0 ; i < arr.length; i++ )
        if(arr[i] == value)
            return i;         // return the index of the element
    return -1                 // otherwise -1
}

while (true) {
   Integer i;
   i = indexOf(foo,"a")
   if (i == -1) break;
   foo[i] = foo[0];           // preserve foo[0]
   foo.drop(1);
}

刪除幾個相等條目中的第一個
使用 lambda

boolean[] done = {false};
String[] arr = Arrays.stream( foo ).filter( e ->
  ! (! done[0] && Objects.equals( e, item ) && (done[0] = true) ))
    .toArray(String[]::new);

可以刪除null條目

在像這樣的字符串數組中

String name = 'abcdeafbde' // 可能類似於 String name = 'aa bb cde aa f bb d e'

我建立了以下課程

class clearname{
def parts
def tv
public def str = ''
String name
clearname(String name){
    this.name = name
    this.parts = this.name.split(" ")
    this.tv = this.parts.size()
}
public String cleared(){

        int i
        int k
        int j=0        
    for(i=0;i<tv;i++){
        for(k=0;k<tv;k++){
            if(this.parts[k] == this.parts[i] && k!=i){
               this.parts[k] = '';
                j++
            }
        }
    }
    def str = ''
    for(i=0;i<tv;i++){
        if(this.parts[i]!='')

           this.str += this.parts[i].trim()+' '
    } 
    return this.str    
}}



return new clearname(name).cleared()

得到這個結果

abcdef

希望此代碼可以幫助任何人

class sd 
{
 public static void main(String[ ] args)
 {
     System.out.println("Search and Delete");

    int key;
    System.out.println("Enter the length of array:");
    Scanner in=new Scanner(System.in);
    int n=in.nextInt();
    int numbers[]=new int[n];

      int i = 0;
      boolean found = false;  
      System.out.println("Enter the elements in Array :");
      for ( i = 0; i < numbers.length; i++)
      {
          numbers[i]=in.nextInt();
      }
      System.out.println("The elements in Array are:");
      for ( i = 0; i < numbers.length; i++)
      {
          System.out.println(numbers[i]);
      }
      System.out.println("Enter the element to be searched:");
      key=in.nextInt();
      for ( i = 0; i < numbers.length; i++)
      {
             if (numbers[ i ]  == key)
            {
                     found = true;      
                     break;
             }
       }
      if (found)   
      {
            System.out.println("Found " + key + " at index " + i + ".");
            numbers[i]=0;//haven't deleted the element in array
            System.out.println("After Deletion:");
        for ( i = 0; i < numbers.length; i++)
          {
              if (numbers[ i ]!=0)
            {   //it skips displaying element in array
                        System.out.println(numbers[i]);
            }
          }
      }
      else
      {
            System.out.println(key + "is not in this array.");
      }
  }
}//Sorry.. if there are mistakes.

采用:

list.removeAll(...);
//post what char you need in the ... section

將 null 分配給數組位置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM