2008-09-24 6 views
20

자바에서는 어떤 필드가 null 일 수있는 클래스를 사용합니다. 예를 들어 :compare()에서 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.barnull을 할 수있다는 사실에 대처하는 표준 방법이 있나요 , 중첩 된 많이 쓰지 않고 if ... else?

건배!

답변

36

난 당신이 높거나 낮은 널 (null)를 정렬하는 작은 정적 메소드와 필드 compareTo 메소드에 대한 호출을 래핑 수도 있겠죠

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

주제에서 벗어났습니다.하지만,// ​​1 이상에서 MIN/MAX_VALUE을 선호하는 이유는 무엇입니까? –

+6

지연 응답 시간에 늦어서 죄송합니다. 삼각형의 불평등을 확실히하기 위해서입니다. > b> c의 경우 a.compareTo (b) + b.compareTo (c) <= a.compareTo (c). 아무도 신경 쓰지 않을 것입니다 ... –

+0

o1/o2가 null 인 경우에도 여전히 'NullPointerException'을 throw 할 수 있습니다. o1/o2가 null 인 경우 어떻게 처리해야합니까? OP 언급 : o1, o2, o1.bar, o2.bar는 null 일 수 있습니다. 아니면 비교 자 계약의 일부입니까? null을 비교하면 NPE가 발생해야합니까? – Daniel

1

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

0

은 일찍 복귀 문이 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. 
6

null 엔트리를 비교할 가치가있는 유효한 문자열 값으로 간주하는지 여부에 따라 달라집니다. null은 < 또는> "apple"입니다. 내가 말할 수있는 유일한 것은 null == null입니다. 순서가 null 인 부분을 정의 할 수 있으면 코드를 적절하게 작성할 수 있습니다.

이 경우 NullPointerExcpetion 또는 IllegalArgumentException을 던지고 처음부터 비교하지 않으므로 상위 수준에서 null을 처리하도록 선택할 수 있습니다. (평소처럼 여러 필드입니다)

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

간단한 사용법 :

+0

나는이 대답을 좋아한다. 감사! – Burkhard

2

여기서 중요한 점은 nulls를 처리하는 방법을 알아내는 것입니다. 일부 옵션은 다음과 같습니다. a) 널 (null)이 정렬 순서대로 다른 모든 오브젝트보다 먼저 온다고 가정하십시오. b) 널 (null)이 정렬 순서의 다른 모든 오브젝트 뒤에옵니다. c) 널 (NULL)을 디폴트 값으로 처리합니다. 어느 것을 선택하는지는 전적으로 귀하가 작업하고있는 응용 프로그램에 달려 있습니다.

물론 마지막 경우에는 예외가 발생합니다. 나머지는 네 가지 방법으로 if/else 케이스가 필요합니다 (결과를 원하는대로 코딩 한 후 약 3 분간 코딩했습니다).

2

Google 컬렉션을 사용하는 경우 Comparators 클래스가 도움이 될 수 있습니다. if는 컬렉션에서 가장 큰 요소 또는 가장 작은 요소 중 하나로 null을 정렬하는 도우미 메서드를가집니다. compound comparators을 사용하면 코드 양을 줄일 수 있습니다.

8

답장을 보내 주셔서 감사합니다. 제네릭 메서드와 Google Comparators는 재미있어합니다.

내가 (우리가 현재 사용하고있는)을 Apache Commons CollectionsNullComparator가 있다는 것을 발견

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 필드에 초점을 맞추었다.

+1

Javadocs에 대한 링크가 죽은 것 같습니다. 현재 http://commons.apache.org/proper/commons-collections/javadocs/api-release/index.html에 있습니다. – JBert

1

NullComparator는 모든 비교 작업에 대해 클래스의 새 인스턴스를 만드는 것과 같은 방식으로 사용하면 안됩니다. 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); 
    } 
} 
+0

맞습니다. NullComparator는 개인 정적 필드 여야합니다. 나는 그 방법으로 무효에 초점을 맞추는 예문을 썼다. –

3

당신은 그것을 위해 비교기를 작성할 수 있습니다. 개인 필드로 문자열 이름이있는 Person 클래스가 있다고 가정 해 보겠습니다. getName() 및 setName() 메서드를 사용하여 필드 이름에 액세스합니다. 아래는 Person 클래스의 Comparator입니다.

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

업데이트 :

자바 (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)); 
2

스프링 프레임 워크에는 org.springframework.util.comparator.NullSafeComparator 클래스가 있습니다.

예 (자바 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); 

이 인쇄됩니다하십시오 POJO.My 응답으로 고객을 고려

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

은 다음과 같습니다

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

또는

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