문제

Java에서는 일부 필드가 될 수있는 클래스를 사용합니다. null. 예를 들어:

class Foo {
    String bar;
    //....
}

이 수업을 위해 BarComparator를 작성하고 싶습니다.

    private static class BarComparator
            implements Comparator<Foo> {
        public int compare( final Foo o1, final Foo o2 )
        {
            // Implementation goes here
        }
    }

사실을 다루는 표준 방법이 있습니까? o1, o2, o1.bar, o2.bar 할 수 있습니다 null, 많은 중첩을 쓰지 않고 if...else?

건배!

도움이 되었습니까?

해결책

널을 높거나 낮게 정렬하기 위해 작은 정적 메소드로 필드 비교 방법으로 호출을 랩핑 할 수 있다고 생각합니다.

static <T extends Comparable<T>> int cp(T a, T b) {
     return
         a==null ?
         (b==null ? 0 : Integer.MIN_VALUE) :
         (b==null ? Integer.MAX_VALUE : a.compareTo(b));
}

간단한 사용법 (여러 필드는 평소와 마찬가지로) :

public int compare( final Foo o1, final Foo o2 ) {
    return cp(o1.field, o2.field);
}

다른 팁

답장 주셔서 감사합니다! 일반적인 방법과 Google 비교기는 흥미로워 보입니다.

그리고 나는 a가 있음을 알았습니다 null comparator 에서 아파치 커먼즈 컬렉션 (현재 우리가 사용하고있는) :

private static class BarComparator
        implements Comparator<Foo>
{
    public int compare( final Foo o1, final Foo o2 )
    {
        // o1.bar & o2.bar nulleness is taken care of by the NullComparator.
        // Easy to extend to more fields.
        return NULL_COMPARATOR.compare(o1.bar, o2.bar);
    }

    private final static NullComparator NULL_COMPARATOR =
                                            new NullComparator(false);
}

참고 : 나는 bar 요점을 유지하기 위해 여기에 필드.

널 입력을 비교할 수있는 유효한 문자열 값으로 간주하는지 여부에 따라 다릅니다. <또는> "Apple"입니다. 내가 확실히 말할 수있는 유일한 것은 null == null입니다. NULL이 주문에 맞는 위치를 정의 할 수 있다면 코드를 적절하게 쓸 수 있습니다.

이 경우 나는 nullpointerexcpetion 또는 delegalargumentexception을 던지고 처음에는 비교를하지 않음으로써 더 높은 수준에서 널을 처리하려고 시도 할 수 있습니다.

비교기를 쓸 수 있습니다. 문자열 이름이 개인 필드로 문자열 이름을 가진 클래스 사람이 있다고 가정 해 봅시다. getName () 및 setName () 메소드 필드 이름에 액세스 할 수 있습니다. 아래는 클래스 사람의 비교기입니다.

    Collections.sort(list, new Comparator<Person>() {
        @Override
        public int compare(Person a, Person b) {
            if (a == null) {
                if (b == null) {
                    return 0;
                }
                return -1;
            } else if (b == null) {
                return 1;
            }
            return a.getName().compareTo(b.getName());
        }
    });

업데이트:

Java 8 기준으로 목록에 API 아래를 사용할 수 있습니다.

// Push nulls at the end of List
Collections.sort(subjects1, Comparator.nullsLast(String::compareTo));

// Push nulls at the beginning of List
Collections.sort(subjects1, Comparator.nullsFirst(String::compareTo));

여기서 핵심은 널스를 어떻게 처리하고 싶은지 알아내는 것입니다. 일부 옵션은 다음과 같습니다. a) 정렬 순서대로 다른 모든 물체보다 먼저 널이 오기 전에 널이 다른 모든 객체를 정렬 순서대로 나오라고 가정합니다. 당신이 선택한 것을 선택하는 것은 전적으로 작업중인 응용 프로그램에 따라 다릅니다.

물론 마지막 경우에는 예외가 발생합니다. 다른 사람들의 경우 4 방향 IF/ELSE 케이스 (약 3 분 동안 코딩 한 결과를 원료로 만들었습니다)가 필요합니다.

Google 컬렉션을 사용하는 경우 비교기 수업이 도움이됩니다. 컬렉션에서 가장 큰 요소로 널을 주문할 수있는 도우미 방법이있는 경우. 당신이 사용할 수있는 복합 비교기 코드 양을 줄이는 데 도움이됩니다.

수업도 있습니다 org.springframework.util.comparator.NullSafeComparator 스프링 프레임 워크에서 사용할 수 있습니다.

예제 (Java 8) :

SortedSet<Foo> foos = new TreeSet<>( ( o1, o2 ) -> {
        return new NullSafeComparator<>( String::compareTo, true ).compare( o1.getBar(), o2.getBar() );
    } );

    foos.add( new Foo(null) );
    foos.add( new Foo("zzz") );
    foos.add( new Foo("aaa") );

    foos.stream().forEach( System.out::println );

이것은 인쇄 할 것입니다 :

Foo{bar='null'}
Foo{bar='aaa'}
Foo{bar='zzz'}

나에게는 그것을 할 방법이 없지만 어쨌든 코드는 그리 길지 않습니다.

당신은 당신이하는 방식으로 null comparator를 사용해서는 안됩니다 - 당신은 모든 비교 작업에 대한 새로운 클래스 인스턴스를 만들고, 예를 들어 1000 개의 항목으로 목록을 정렬하면 1000 * log2 (1000) 객체가 될 것입니다. 완전히 불필요합니다. 이것은 빠르게 문제가 될 수 있습니다.

서브 클래스 또는이를 위임하거나 단순히 자신의 널 확인을 구현하십시오. 실제로 그렇게 복잡하지 않습니다.

private static class BarComparator
        implements Comparator<Foo> {
    private NullComparator delegate = new NullComparator(false);

    public int compare( final Foo o1, final Foo o2 )
    {
        return delegate.compare(o1.bar, o2.bar);
    }
}

고객을 pojo로 고려합니다. 내 대답은 다음과 같습니다.

Comparator<Customer> compareCustomer = Comparator.nullsLast((c1,c2) -> c1.getCustomerId().compareTo(c2.getCustomerId()));

또는

Comparator<Customer> compareByName = Comparator.comparing(Customer::getName,nullsLast(String::compareTo));

초기 반환 진술은 많은 IFS에 대한 다른 대안이 될 것이라고 생각합니다.

예를 들어

if(o1==null) return x;
if(o2==null) return x;
if(o1.getBar()==null) return x;
if(o2.getBar()==null) return x;

// No null checks needed from this point.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top