programing

Array List 또는 String Array에서 모든 null 요소를 효율적으로 삭제하는 방법

prostudy 2022. 7. 16. 13:53
반응형

Array List 또는 String Array에서 모든 null 요소를 효율적으로 삭제하는 방법

나는 그렇게 루프로 시도한다.

// ArrayList tourists

for (Tourist t : tourists) {
    if (t != null) {     
        t.setId(idForm); 
    }   
}

하지만 좋지 않아요.누가 더 나은 해결책을 제안해 줄 수 있나요?


보다 나은 결정을 내리기 위한 유용한 벤치마크:

While loop, For loop 및 Iterator 성능 테스트

시험:

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));

지원되지 않음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)입니다.

싱글톤을 모두 삭제해야 합니다.내부적으로는 읽기 위치와 쓰기 위치가 있는 batch Remove()가 실행됩니다.그리고 목록을 반복합니다.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) 연산입니다.

가장 빠른 것은 목록을 양쪽 끝에서 반복하여 늘을 발견했을 때 그 값을 마지막에 찾은 값과 동일하게 설정하고 그 값을 줄이는 것입니다.그리고 두 값이 일치할 때까지 반복했다.순서는 엉망이지만, 방치된 값보다 설정한 값의 수가 크게 줄어듭니다.이것은 좋은 방법이지만, .set()은 기본적으로 무료이기 때문에 여기서는 별로 도움이 되지 않지만, 그러한 형태의 삭제는 벨트에 유용한 도구입니다.


for (Iterator<Tourist> itr = tourists.iterator(); itr.hasNext();) {
      if (itr.next() == null) { itr.remove(); }
 }

이 정도면 타당하다고 생각되지만, 리테이터의 .remove()는 내부적으로 다음과 같이 호출합니다.

ArrayList.this.remove(lastRet);

이는 다시 제거 내의 O(n) 연산입니다.시스템이 동작합니다.arraycopy()는 속도에 관심이 있는 경우 원하는 것이 아닙니다.이것은 n^2가 됩니다.

또, 다음과 같은 것도 있습니다.

while(tourists.remove(null));

즉 O(m*n^2)입니다.여기서는 목록만 반복하는 것이 아닙니다.null과 일치할 때마다 목록 전체를 반복합니다.그런 다음 시스템을 실행하기 위해 n/2(평균) 연산을 수행합니다.arraycopy()를 지정하여 삭제합니다.문자 그대로 값을 가진 항목과 null 값을 가진 항목 간에 전체 컬렉션을 정렬하고 짧은 시간 내에 엔딩을 자를 수 있습니다.사실, 그것은 모든 부서진 것들에 해당된다.적어도 이론상으론, 실제 시스템이지.실제로 어레이 복사는 N개의 작업이 아닙니다.이론적으로는 이론과 실제는 같지만 실제로는 그렇지 않다.

Objects에는 '''가 .nonNull Predicate 사용할 수 .filter.

예를 들어 다음과 같습니다.

tourists.stream().filter(Objects::nonNull).collect(Collectors.toList());

8을 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

주로 사용하고 있는 것은 다음과 같습니다.

list.removeAll(Collections.singleton(null));

하지만 Java 8을 배운 후, 다음과 같이 전환했습니다.

List.removeIf(Objects::isNull);

할 수 있는 이 있습니다.null「」의 값collection을 「null」로 해 주세요.removeAll()

List s1=new ArrayList();
s1.add(null);

yourCollection.removeAll(s1);

이렇게 하면 어레이 목록에서 기본 null 값을 쉽게 제거할 수 있습니다.

     tourists.removeAll(Arrays.asList(null));  

그렇지 않으면 문자열 값 "null"을 배열 목록에서 제거합니다.

       tourists.removeAll(Arrays.asList("null"));  

이걸 가지고 놀았더니 trim To Size()가 작동하는 것 같아요.저는 안드로이드 플랫폼을 사용하고 있기 때문에 다를 수 있습니다.

같은 방법으로 반복기를 사용하여 모든 null 값을 제거할 수 있습니다.

Iterator<Tourist> itr= tourists.iterator();
while(itr.hasNext()){
    if(itr.next() == null){
        itr.remove();
    }
}

스트림 인터페이스를 스트림 오퍼레이션 수집 및 도우미 메서드와 함께 사용하여 새 목록을 생성했습니다.

tourists.stream().filter(this::isNotNull).collect(Collectors.toList());

private <T> boolean isNotNull(final T item) {
    return  item != null;
}

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 answer와 비슷하지만 "List may not contain type null" 오류는 발생하지 않습니다.

   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);

언급URL : https://stackoverflow.com/questions/4819635/how-to-efficiently-remove-all-null-elements-from-a-arraylist-or-string-array

반응형