Ответ 1
list.removeAll(Collections.singleton(null));
Учитывая следующий список:
List<String> list = new ArrayList<String>();
list.add("s1");
list.add("s2");
list.add(null);
list.add("s3");
list.add(null);
list.add("s4");
Мне нужен вспомогательный класс, который удаляет нулевые ссылки. Что-то вроде:
SomeHelper.removeNullReference(список);
так что список содержит только "s1", "s2", "s4", "s4" (непустые ссылки).
Что следует использовать для выполнения этого требования?
list.removeAll(Collections.singleton(null));
Java 8 добавила Collection.removeIf(Predicate)
, которая удаляет все элементы, соответствующие предикату, поэтому вы можете удалить все вхождения null
из списка ( или любой коллекции) с помощью
list.removeIf(Objects::isNull);
используя java.util.Objects.isNull
как Predicate
.
Вы также можете использовать .removeIf(x -> x == null)
, если хотите; разница очень незначительная.
Если вы можете управлять созданием List
, тогда вы можете предотвратить добавление нулей путем записи пользовательской реализации List
, например:
public class NoNullsList<E> extends ArrayList<E> {
public void add(int index, E element) {
if (element != null) {
super.add(index, element);
}
}
public boolean add(E e) {
return e == null ? false : super.add(e);
}
}
AFAIK, вам не нужно переопределять addAll
, потому что его реализация ArrayList
вызывает add
.
List<String> list = new NoNullsList<String>();
list.add("s1");
list.add("s2");
list.add(null);
list.add("s3");
list.add(null);
list.add("s4");
Недостатком подхода Don является то, что он простирается от ArrayList
. На данный момент это может быть достаточно хорошим, но что происходит, когда вы хотите использовать другую реализацию List
? Вы можете сделать NoNullsLinkedList
и NoNullsCopyOnWriteArrayList
, и т.д., Но затем вы соберете кучу небольших классов, которые отличаются только их предложением extends
. Возможно, было бы лучше создать оболочку List
, которая не принимает значения null. Например:
public class NonNullList<E> extends AbstractList<E> {
private final List<E> delegate;
public NonNullList(List<E> delegate) {
this.delegate = delegate;
}
@Override
public E get(int index) {
return delegate.get( index );
}
@Override
public int size() {
return delegate.size();
}
@Override
public E set(int index, E element) {
return delegate.set( index, element );
}
@Override
public void add(int index, E element) {
if( element != null ) {
delegate.add( index, element );
}
}
@Override
public E remove(int index) {
return delegate.remove( index );
}
}
Это больше кода, но теперь у вас есть гибкость при выборе реализации List
при создании объекта.
Возможная проблема заключается в том, что вы можете поместить null
в базовый объект List
. Дон подход не имеет того же ограничения.
Мне очень нравится новое сжатое решение Java 8, я считаю, что вы должны использовать это, когда это возможно.
list.removeIf(Objects::isNull);
С другой стороны, если вы ищете простую реализацию, чтобы узнать, как это можно сделать, например, вспомогательный класс, который возвращает новый ненулевой список, вы можете взглянуть на следующий код. Также можно принять общие типы, для простоты я использовал один и тот же тип коллекции (как в вопросе) в классе-помощнике.
package removenullrefdemo;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
class ListHelper {
public static List<String> removeNullReference(List<String> list) {
List<String> newList = new ArrayList<>();
list.forEach(item -> {
if (item != null)
newList.add(item);
});
return newList;
}
}
public class Main {
public static void main(String[] args) {
List<String> list = new ArrayList<String>();
list.add("s1");
list.add("s2");
list.add(null);
list.add("s3");
list.add(null);
list.add("s4");
println("Items:");
list.forEach(item -> println(item));
// Remove null refs
println("Items (after nulls removed):");
boolean useJava8removeIf = false;
if (useJava8removeIf) {
println("Using Java8 removeIf method with predicate.");
list.removeIf(Objects::isNull);
}
else {
println("Using our own helper.");
list = ListHelper.removeNullReference(list);
}
list.forEach(item -> println(item));
}
static void println(String msg) {
System.out.println(msg);
}
}
removeAll не работает для меня. Вместо этого я создаю новый список:
new ArrayList<E>(list);
Просто как это.