[英]How to remove all null elements from a ArrayList or String Array?
我嘗試使用這樣的循環
// ArrayList tourists
for (Tourist t : tourists) {
if (t != null) {
t.setId(idForm);
}
}
但這並不好。 誰能建議我一個更好的解決方案?
一些有用的基准可以做出更好的決策:
截至 2015 年,這是最好的方法(Java 8):
tourists.removeIf(Objects::isNull);
注意:對於固定大小的列表(例如使用 Arrays.asList 創建),包括不可變列表,此代碼將拋出java.lang.UnsupportedOperationException
。
list.removeAll(Collections.singleton(null));
如果你在 Arrays.asList 上使用它,它會拋出UnsupportedException因為它給你不可變的副本所以它不能被修改。 請參閱下面的代碼。 它創建可變副本並且不會拋出任何異常。
public static String[] clean(final String[] v) {
List<String> list = new ArrayList<String>(Arrays.asList(v));
list.removeAll(Collections.singleton(null));
return list.toArray(new String[list.size()]);
}
效率不高,但很短
while(tourists.remove(null));
如果您更喜歡不可變數據對象,或者您只是不想破壞輸入列表,則可以使用 Guava 的謂詞。
ImmutableList.copyOf(Iterables.filter(tourists, Predicates.notNull()))
for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
if (itr.next() == null) { itr.remove(); }
}
您應該使用 Java 8 之前的版本:
tourists.removeAll(Collections.singleton(null));
后 Java 8 使用:
tourists.removeIf(Objects::isNull);
這里的原因是時間復雜度。 數組的問題是刪除操作可能需要 O(n) 時間才能完成。 實際上,在 Java 中,這是剩余元素的數組副本,用於替換空白位置。 此處提供的許多其他解決方案將觸發此問題。 前者在技術上是 O(n*m),其中 m 是 1,因為它是一個單例 null:所以 O(n)
您應該刪除所有的單例,它在內部執行一個具有讀取位置和寫入位置的 batchRemove()。 並迭代列表。 當它遇到一個空值時,它只是將讀取位置迭代 1。當它們相同時它通過,當它們不同時它繼續復制值。 然后在最后它修剪到大小。
它在內部有效地做到了這一點:
public static <E> void removeNulls(ArrayList<E> list) {
int size = list.size();
int read = 0;
int write = 0;
for (; read < size; read++) {
E element = list.get(read);
if (element == null) continue;
if (read != write) list.set(write, element);
write++;
}
if (write != size) {
list.subList(write, size).clear();
}
}
您可以明確看到是 O(n) 操作。
唯一可能更快的是,如果您從兩端迭代列表,當您找到一個空值時,您將它的值設置為您在最后找到的值,然后遞減該值。 並迭代直到兩個值匹配。 您會弄亂順序,但會大大減少您設置的值與您單獨留下的值的數量。 這是一個很好的了解方法,但在這里沒有多大幫助,因為 .set() 基本上是免費的,但這種刪除形式對您的腰帶來說是一個有用的工具。
for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
if (itr.next() == null) { itr.remove(); }
}
雖然這看起來很合理,但迭代器上的 .remove() 內部調用:
ArrayList.this.remove(lastRet);
這又是移除中的 O(n) 操作。 如果您關心速度,它會執行 System.arraycopy() 這又不是您想要的。 這使它成為 n^2。
還有:
while(tourists.remove(null));
這是 O(m*n^2)。 這里我們不僅迭代列表。 每次我們匹配空值時,我們都會重申整個列表。 然后我們執行 n/2(平均)操作來執行 System.arraycopy() 以執行刪除。 從字面上看,您可以在具有值的項目和具有空值的項目之間對整個集合進行排序,並在更短的時間內修剪結尾。 事實上,對於所有破碎的人來說都是如此。 至少在理論上,實際的 system.arraycopy 實際上並不是一個 N 操作。 理論上,理論和實踐是一回事; 實際上他們不是。
使用 Java 8,您可以使用stream()
和filter()
tourists = tourists.stream().filter(t -> t != null).collect(Collectors.toList())
或
tourists = tourists.stream().filter(Objects::nonNull).collect(Collectors.toList())
有關更多信息: Java 8 - 流
Objects
類具有可與filter
一起使用的nonNull
Predicate
。
例如:
tourists.stream().filter(Objects::nonNull).collect(Collectors.toList());
我主要是用這個:
list.removeAll(Collections.singleton(null));
但是在我學習了 Java 8 之后,我轉向了這個:
List.removeIf(Objects::isNull);
有一種簡單的方法可以從collection
中刪除所有null
值。您必須將包含空值的集合作為參數傳遞給removeAll()
方法
List s1=new ArrayList();
s1.add(null);
yourCollection.removeAll(s1);
這是從數組列表中刪除默認空值的簡單方法
tourists.removeAll(Arrays.asList(null));
否則字符串值“null”從數組列表中刪除
tourists.removeAll(Arrays.asList("null"));
我們可以使用迭代器來刪除所有空值。
Iterator<Tourist> itr= tourists.iterator();
while(itr.hasNext()){
if(itr.next() == null){
itr.remove();
}
}
我將流接口與流操作collect和輔助方法一起使用來生成新列表。
tourists.stream().filter(this::isNotNull).collect(Collectors.toList());
private <T> boolean isNotNull(final T item) {
return item != null;
}
我玩弄了這個,發現 trimToSize() 似乎有效。 我在 Android 平台上工作,所以它可能會有所不同。
使用Java 8,可以使用流、並行流和removeIf
方法以各種方式執行此操作:
List<String> stringList = new ArrayList<>(Arrays.asList(null, "A", "B", null, "C", null));
List<String> listWithoutNulls1 = stringList.stream()
.filter(Objects::nonNull)
.collect(Collectors.toList()); //[A,B,C]
List<String> listWithoutNulls2 = stringList.parallelStream()
.filter(Objects::nonNull)
.collect(Collectors.toList()); //[A,B,C]
stringList.removeIf(Objects::isNull); //[A,B,C]
並行流將利用可用的處理器,並將加速合理大小列表的過程。 始終建議在使用流之前進行基准測試。
類似於@Lithium 答案,但不會拋出“列表可能不包含空類型”錯誤:
list.removeAll(Collections.<T>singleton(null));
List<String> colors = new ArrayList<>(
Arrays.asList("RED", null, "BLUE", null, "GREEN"));
// using removeIf() + Objects.isNull()
colors.removeIf(Objects::isNull);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.