我尝试使用这样的循环
// ArrayList tourists
for (Tourist t : tourists) {
if (t != null) {
t.setId(idForm);
}
}
但这并不好。谁能建议我一个更好的解决方案?
做出更好决策的一些有用的基准:
答案 0 :(得分:350)
尝试:
tourists.removeAll(Collections.singleton(null));
阅读Java API。代码将为不可变列表抛出java.lang.UnsupportedOperationException
(例如使用Arrays.asList
创建);有关详细信息,请参阅this answer。
答案 1 :(得分:97)
截至2015年,这是最好的方式(Java 8):
tourists.removeIf(Objects::isNull);
注意:此代码将为固定大小的列表(例如使用Arrays.asList创建)抛出java.lang.UnsupportedOperationException
,包括不可变列表。
答案 2 :(得分:45)
list.removeAll(Collections.singleton(null));
如果您在Arrays.asList上使用它,它将抛出 UnsupportedException ,因为它会为您提供不可变副本,因此无法修改它。见下面的代码。它会创建 Mutable 副本,不会抛出任何异常。
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()]);
}
答案 3 :(得分:18)
效率不高,但很短
while(tourists.remove(null));
答案 4 :(得分:18)
如果您更喜欢不可变数据对象,或者您只是不想破坏输入列表,则可以使用Guava的谓词。
ImmutableList.copyOf(Iterables.filter(tourists, Predicates.notNull()))
答案 5 :(得分:7)
for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
if (itr.next() == null) { itr.remove(); }
}
答案 6 :(得分:3)
有一种简单的方法可以从null
中删除所有collection
值。您必须将包含null的集合作为参数传递给removeAll()
方法
List s1=new ArrayList();
s1.add(null);
yourCollection.removeAll(s1);
答案 7 :(得分:3)
Objects
班级有nonNull
Predicate
,可与filter
一起使用。
例如:
tourists.stream().filter(Objects::nonNull).collect(Collectors.toList());
答案 8 :(得分:3)
使用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 - Streams
答案 9 :(得分:3)
Pre-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()。并迭代列表。当它达到null时,它只是将读取位置迭代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)操作。
唯一可能更快的是,如果从两端迭代列表,并且当找到null时,将其值设置为等于最后找到的值,并递减该值。并迭代,直到两个值匹配。你搞砸了订单,但会大大减少价值 你设置与你独自留下的人。这是一个很好的方法,但在这里帮助不大,因为.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)。在这里,我们不仅迭代列表。我们重复整个列表,每次匹配null。然后我们进行n / 2(平均)操作来执行System.arraycopy()来执行删除。 您可以完全按照字面意思,使用值和具有空值的项目对项目之间的整个集合进行排序,并在更短的时间内修剪结尾。事实上,对于所有破碎的人来说都是如此。至少在理论上,实际的system.arraycopy实际上并不是N操作。从理论上讲,理论和实践是一回事;实际上他们不是。
答案 10 :(得分:2)
这是从arraylist
中删除默认空值的简便方法 tourists.removeAll(Arrays.asList(null));
否则字符串值“null”从arraylist中删除
tourists.removeAll(Arrays.asList("null"));
答案 11 :(得分:1)
我玩弄了这个并发现trimToSize()似乎有效。我正在Android平台上工作,所以可能会有所不同。
答案 12 :(得分:1)
我们可以使用迭代器来删除所有空值。
Iterator<Tourist> itr= tourists.iterator();
while(itr.hasNext()){
if(itr.next() == null){
itr.remove();
}
}
答案 13 :(得分:1)
我将流接口与流操作收集和辅助方法一起使用以生成新列表。
tourists.stream().filter(this::isNotNull).collect(Collectors.toList());
private <T> boolean isNotNull(final T item) {
return item != null;
}
答案 14 :(得分:1)
主要是我在用这个:
list.removeAll(Collections.singleton(null));
但是在我学习Java 8之后,我切换到了这个地方
List.removeIf(Objects::isNull);
答案 15 :(得分:0)
使用 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]
并行流将利用可用的处理器,并将加速合理大小的列表的过程。在使用流之前始终建议进行基准测试。
答案 16 :(得分:0)
与@Lithium答案类似,但不会抛出&#34; List可能不包含类型null&#34;错误:
list.removeAll(Collections.<T>singleton(null));
答案 17 :(得分:0)
List<String> colors = new ArrayList<>(
Arrays.asList("RED", null, "BLUE", null, "GREEN"));
// using removeIf() + Objects.isNull()
colors.removeIf(Objects::isNull);