2009-11-21 53 views
-1

我想做一個工作列表的數組實施的刪除方法。 我可以將重複元素設置爲null以將其刪除嗎?假設列表是有序的。在java中刪除數組中的元素,你可以將它設置爲null?

ArrayList a = new ArrayList[]; 

public void removeduplicates(){ 

    for(a[i].equals(a[i+1]){ 

     a[i+1] = null; 

    } 
    a[i+1] = a[i]; 
} 
+6

此代碼是否編譯? – 2009-11-21 23:25:02

+0

要格式化代碼,請選擇它並按Ctrl + K(或者在每行的開頭放置四個空格)。 – 2009-11-21 23:30:51

+2

也許你應該用Set來代替? http://java.sun.com/j2se/1.4.2/docs/api/java/util/Set.html – 2009-11-21 23:31:17

回答

3

不,您不能從數組中刪除元素,因爲它使得它更短。 Java數組是固定大小的。你需要使用ArrayList

如果將元素設置爲null,則該數組將仍具有相同的大小,但在該點處具有空引用。

// Let's say a = [0,1,2,3,4] (Integer[]) 
a[2] = null; 
// Now a = [0,1,null,3,4] 
2

是的,你可以在一個陣列空集的元素,但如果數組包含空值像a[i].equals(a[i+1])代碼將失敗,一個NullPointerException,那麼你就必須要更加小心,如果你知道你的數組可能包含空值。它也不會更改數組的大小,因此如果刪除大量元素,則會浪費內存。如果您經常添加和刪除元素,則固定大小的數組通常不是一種存儲數據的好方法 - 正如您可以從他們的名字中猜出的那樣。

1

不,包含null的數組元素仍然存在,它只是不包含任何有用的值。

您可以嘗試將列表中的每個元素從列表中向下移動1個元素以填充空白處,然後在數組的末尾有空隙 - 數組不會縮小!

如果您要做的很多,可以使用System.arraycopy()快速完成此打包操作。

2

我可以設置重複元素設置爲null將其刪除?

您可以設置陣列null的元素,但這不會刪除數組的元素...它只是設置元素null(我覺得重複第一句)。

您應該返回數組的清理副本。要做到這一點的方法之一是使用中介java.util.Set

String[] data = {"A", "C", "B", "D", "A", "B", "E", "D", "B", "C"}; 

// Convert to a list to create a Set object 
List<String> list = Arrays.asList(data); 
Set<String> set = new HashSet<String>(list); 

// Create an array to convert the Set back to array. 
String[] result = new String[set.size()]; 
set.toArray(result); 

或者,也許只是使用java.util.Set :)

2

直進回答你的問題是,設置一個數組或ArrayList的元素設置爲null爲您提供數組或ArrayList中的空條目。這與刪除元素不同。如果只是意味着a[i]a.get(i)將返回null而不是原始元素。

問題中的代碼出現亂碼。如果你要使用ArrayList中,simplisitic的解決辦法是這樣的:

ArrayList a = new ArrayList(); 

public void removeduplicates() { 
    for (int i = 0; i < a.size() - 1;) { 
     if (a.get(i).equals(a.get(i + 1)) { 
      a.remove(i); 
     } else { 
      i++; 
     } 
    } 
} 

,但在最壞的情況下,這是O(N**2)因爲每次調用remove副本的所有元素的索引比當前值i

如果你想提高性能,做這樣的事情:

public ArrayList removeduplicates() { 
    ArrayList res = new ArrayList(a.size()); 
    if (a.size() == 0) { 
     return res; 
    } 
    res.add(a.get(0)); 
    for (int i = 1; i < a.size(); i++) { 
     if (!a.get(i - 1).equals(a.get(i)) { 
      res.add(a.get(i)); 
     } 
    } 
    return res; 
} 

(這是一個快速劈我敢肯定,它可以被收拾。)

+0

這就是爲什麼鏈表更適合這種特殊情況的原因。 – Jherico 2009-11-22 00:01:50

+0

@Jherico ......這取決於你在列表中做了什麼以及你將要做多次刪除的可能性。 'O(N ** 2)'是最糟糕的行爲。另外,我在最壞的情況下只添加了一個'O(N)'的版本。 – 2009-11-22 00:08:35

+0

@Stephen,但使用'O(N)'額外存儲。 – 2009-11-22 00:26:21

2

這是一門功課題?

您的問題類似於流處理程序uniq:保留 - 通過複製 - 與之前不匹配的任何元素。它只刪除所有重複如果序列排序。否則,它只會刪除連續的重複項。這意味着當決定是否在序列中稍後保留元素時,您最多需要緩衝一個元素(即使通過引用)以用作比較謂詞。

唯一的特例是第一個元素。因爲它不應該匹配任何前面的元素,所以您可以嘗試將緩衝的「previous」元素初始化爲某個超出序列類型域的值,或者可以使用「第一個元素」標誌或明確指定您的迭代複製迭代之外的第一個元素 - 關注序列爲空的情況。

請注意,我並不建議您提供此操作作爲破壞性就地算法。這隻適用於類似鏈接列表的結構,並且具有移除元素的常量開銷。正如其他人在這裏指出的那樣,從數組或向量中移除元素涉及對後續元素進行隨機填充以填充後續元素的時間複雜度爲n

2

你的代碼示例很混亂。用ArrayList[]你顯示了一個ArrayList對象的數組。

假設你只是在談論java.util.ArrayList,那麼最簡單的方法就是使用java.util.Set來代替重複項,正如其他人所說的那樣。如果你真的想擁有,startwith,或用List由於某些原因最終然後執行:

List withDuplicates = new ArrayList() {{ add("foo"); add("bar"); add("waa"); add("foo"); add("bar"); }}; // Would rather have used Arrays#asList() here, but OK. 
List withoutDuplicates = new ArrayList(new LinkedHashSet(withDuplicates)); 
System.out.println(withoutDuplicates); // [foo, bar, waa] 

LinkedHashSet在這裏選擇,因爲它保持了排序。如果您不擔心訂購,HashSet會更快。但是,如果你真的想要分類,TreeSet可能更有價值。另一方面,如果您正在討論real array,並且您想在沒有(很好)Collections framework的幫助下過濾出重複項,那麼您需要創建另一個數組並逐個添加項目當你檢查數組是否已經包含了要添加的項目時。這裏有一個基本的例子(沒有的Arrays.sort()Arrays.binarySearch()這將緩解任務更多的幫助,但你最終會得到一個有序數組):

String[] array1 = new String[] {"foo", "bar", "foo", "waa", "bar"}; 
String[] array2 = new String[0]; 

loop:for (String array1item : array1) { 
    for (String array2item : array2) { 
     if (array1item.equals(array2item)) { 
      continue loop; 
     } 
    } 
    int length = array2.length; 
    String[] temp = new String[length + 1]; 
    System.arraycopy(array2, 0, temp, 0, length); 
    array2 = temp; 
    array2[length] = array1item; 
} 

System.out.println(Arrays.toString(array2)); // [foo, bar, waa] 

希望這給了新的見解。

2

如果你正在實現你自己的列表,並且你決定使用基本的基元存儲機制。因此使用數組(而不是數組列表)可能是您開始的地方。

對於簡單的實施,您的策略應考慮以下幾點。

決定如何擴展您的列表。您可以一次實例化200個單元的數據塊。您只能使用199,因爲您可能想要使用最後一個單元來存儲下一個分配塊。

這樣的鏈表很糟糕,所以你可能決定使用一個主塊來存儲塊的所有實例。您實例化一個大小爲100的主塊。您從一個200的數據塊開始,並將其參考值存儲在master [0]中。隨着列表大小的增加,您逐漸將master [1] .... master [99]中每個新數據塊的ref存儲起來,然後您可能必須重新創建主列表才能存儲200個引用。

出於效率的原因,當你刪除一個單元格時,你不應該立即消滅它。你讓它掛起來,直到有足夠的刪除來重新創建塊。

您需要以某種方式標記一個單元格已被刪除。所以答案是顯而易見的,當然你可以將它設置爲空,因爲你是國王,皇帝,決定一個單元格被標記爲已刪除的獨裁者。使用null是一種很好而且通常的方式。如果您使用null,那麼您必須禁止將空值作爲數據插入到您的列表類中。如果有這樣的嘗試,你將不得不拋出異常。

您必須設計和編寫一個垃圾回收例程和策略,以通過重新創建塊以刪除無效單元en mass來壓縮列表。 JVM不會知道這些是「已刪除」的數據。

你需要一個寄存器來計算刪除的次數,如果超過了這個閾值,垃圾收集將會啓動。或者你讓程序員決定調用compact()方法。因爲如果刪除是稀疏的並且分佈在各種數據塊中,那麼最好不要留下空/刪除的單元。您只能合併相鄰的塊,並且只有當兩個塊中的孔數總和達到200時,顯然纔是。

也許,當數據被附加到列表中時,您故意在數據之間留下空洞。這就像在街上開車,你看到的房子地址增加10,因爲城市已經決定,如果人們希望在現有房屋之間建造新房。這樣,每次插入時都不必重新創建和分割塊。

因此,答案很明顯,你當然可以寫空來表示一個單元格被刪除,因爲它是你管理列表類的策略。