나는 그런 루프로 시도
// ArrayList tourists
for (Tourist t : tourists) {
if (t != null) {
t.setId(idForm);
}
}
그러나 좋지 않습니다. 누구든지 나에게 더 나은 해결책을 제안 할 수 있습니까?
더 나은 의사 결정을위한 유용한 벤치 마크 :
답변
시험:
tourists.removeAll(Collections.singleton(null));
Java API를 읽으십시오 . 이 코드는 java.lang.UnsupportedOperationException
불변 목록 (예 :로 만든 Arrays.asList
)을 처리합니다. 자세한 내용 은 이 답변 을 참조하십시오.
답변
2015 년 현재 이것이 가장 좋은 방법입니다 (Java 8).
tourists.removeIf(Objects::isNull);
참고 : 이 코드는 java.lang.UnsupportedOperationException
불변 목록을 포함하여 고정 크기 목록 (예 : Arrays.asList로 생성)에 대해 발생합니다.
답변
list.removeAll(Collections.singleton(null));
그것은 것이다 예외 UnsupportedException를 당신에게 제공하기 때문에 당신이 Arrays.asList에 그것을 사용하는 경우 불변 이 변경 될 수 없도록 사본을. 아래 코드를 참조하십시오. 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()]);
}
답변
비효율적이지만 짧음
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입니다. 따라서 O (n)
내부적으로 모든 singleton을 제거해야하며 내부적으로 읽기 위치와 쓰기 위치가있는 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);
이것은 다시 remove 내의 O (n) 연산입니다. 속도에 신경 쓰면 다시 원하지 않는 System.arraycopy ()를 수행합니다. 이것은 n ^ 2가됩니다.
또한있다 :
while(tourists.remove(null));
어느 것이 O (m * n ^ 2)입니다. 여기서 우리는 목록을 반복 할뿐만 아니라 null과 일치 할 때마다 전체 목록을 반복합니다. 그런 다음 n / 2 (평균) 작업을 수행하여 System.arraycopy ()를 수행하여 제거를 수행합니다. 말 그대로 값이있는 항목과 null 값이있는 항목 사이의 전체 컬렉션을 정렬하고 더 적은 시간 안에 끝을자를 수 있습니다. 사실, 그것은 깨진 모든 사람에게 해당됩니다. 적어도 이론 상으로는 실제 system.arraycopy는 실제로 N 작업이 아닙니다. 이론적으로 이론과 실제는 같은 것입니다. 실제로는 그렇지 않습니다.