자바 의 다양한 비교 대상 방식 에 대한 비교 총화

하나,==화!=조작 부호
우리처음에는 두 자바 대상 이 같은 조작 자 인지 아 닌 지 를 각각 판단 할 수 있 었 다.
1.1 원본 형식(Primitives)
원본 유형 에 대해 똑 같은 값 을 가 진 다 는 것 을 의미 합 니 다.

assertThat(1 == 1).isTrue();
자동 으로 상 자 를 뜯 어 주 셔 서 감사합니다. 원 어 값 과 포장 유형 에 대응 하 는 값 을 비교 할 때 도 이렇게 할 수 있 습 니 다.

Integer a = new Integer(1);
assertThat(1 == a).isTrue();
만약 두 정수 의 값 이 다르다 면,==연산 자 는 false 로 돌아 갑 니 다.그리고!=연산 자 는 트 루 로 돌아 갑 니 다.
1.2 대상 비교
만약 에 우리 가 똑 같은 수 치 를 가 진 정수 포장 유형 을 비교 해 야 한다 고 가정 한다.

Integer a = new Integer(1);
Integer b = new Integer(1);

assertThat(a == b).isFalse();
두 대상 을 비교 해 보면 이 대상 들 의 값 은 1 이 아니 라 스 택 에 있 는 메모리 주소 입 니 다.이 두 대상 은 모두 new 연산 자 를 사용 하여 만 들 었 기 때 문 입 니 다.만약 우리 가 a 를 b 에 게 분배 한다 면 우 리 는 다른 결 과 를 얻 을 수 있 을 것 이다.

Integer a = new Integer(1);
Integer b = a;

assertThat(a == b).isTrue();
이제 Integer\#value Of factory 방법 을 사용 할 때 어떤 일이 일어 나 는 지 보 여 줍 니 다.

Integer a = Integer.valueOf(1);
Integer b = Integer.valueOf(1);

assertThat(a == b).isTrue();
이런 상황 에서 그것들 은 같은 것 으로 여 겨 진다.이 는 같은 값 의 포장 기 대상 을 너무 많이 만 들 지 않도록 value Of()방법 으로 정 수 를 캐 시 에 저장 하기 때문이다.따라서 이 방법 은 두 개의 호출 을 위해 같은 정수 인 스 턴 스 를 되 돌려 준다.
문자열 에 대해 서도 마찬가지 입 니 다:

assertThat("Hello!" == "Hello!").isTrue();
하지만 new 연산 자 를 사용 하여 만 들 었 다 면 달라 집 니 다.마지막 으로 두 개의 빈 인용 은 같은 것 으로 여 겨 지고 빈 대상 이 아 닌 모든 빈 대상 은 빈 대상 과 다르다 고 여 겨 집 니 다.

assertThat(null == null).isTrue();
assertThat("Hello!" == null).isFalse();
물론 같은 연산 자의 행 위 는 한계 가 있 을 수 있다.만약 우리 가 서로 다른 주소 에 비 친 두 개의 대상 을 비교 하고 그들의 내부 상태 에 따라 그것들 을 동일 하 게 보고 싶다 면 어떻게 해 야 합 니까?우 리 는 다음 절 에서 어떻게 조작 하 는 지 볼 것 이다.
2.Object 의 equals 방법
이제 우 리 는 equals()방법 으로 더욱 광범 위 한 동등한 개념 을 토론 합 시다.이 방법 은 모든 자바 대상 이 계승 할 수 있 도록 Object 클래스 에서 정 의 된 것 입 니 다.기본 적 인 상황 에서 대상 의 메모리 주 소 를 비교 하기 때문에 작업 방식 은=연산 자 와 같 습 니 다.그러나 우 리 는 이 방법 을 다시 써 서 우리 의 대상 에 대해 무엇 을 의미 하 는 지 정의 할 수 있다.
우선,기 존 대상(예 를 들 어 Integer)에 대한 표현 을 살 펴 보 자.

Integer a = new Integer(1);
Integer b = new Integer(1);

assertThat(a.equals(b)).isTrue();
두 대상 이 동시에 이 방법 은 여전히 true 로 돌아간다.우 리 는 빈 대상 을 방법의 매개 변수 로 전달 할 수 있 지만,물론 호출 방법의 대상 이 될 수 없다 는 것 을 주의해 야 한다.우 리 는 자신의 대상 에 대해 equals()방법 을 사용 할 수 있다.만약 에 우리 에 게 Person 류 가 있다 고 가정 하면:

public class Person {
    private String firstName;
    private String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
우 리 는 두 사람의 내부 상세 한 정보 에 따라 비교 할 수 있 도록 이러한 equals()방법 을 다시 쓸 수 있다.

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person that = (Person) o;
    return firstName.equals(that.firstName) &&
      lastName.equals(that.lastName);
}
3.Objects 의 정적 방법 equals
이제 Objects 의 equals 정적 방법 을 봅 시다.앞에서 말 했 듯 이 null 을 첫 번 째 대상 의 값 으로 사용 할 수 없습니다.그렇지 않 으 면 NullPointer Exception 을 던 집 니 다.Objects 조수 류 의 equals()방법 이 이 문 제 를 해결 했다.그것 은 두 개의 인 자 를 받 아들 여 그것들 을 비교 하 는 동시에 빈 값 을 처리한다.
Person 대상 을 다시 비교 합 시다:

Person joe = new Person("Joe", "Portman");
Person joeAgain = new Person("Joe", "Portman");
Person natalie = new Person("Natalie", "Portman");

assertThat(Objects.equals(joe, joeAgain)).isTrue();
assertThat(Objects.equals(joe, natalie)).isFalse();
앞에서 말 한 바 와 같이 이 방법 은 빈 값 을 처리 합 니 다.따라서 두 인자 가 모두 null 이면 true 로 돌아 갑 니 다.하나의 인자 만 null 이면 false 로 돌아 갑 니 다.이것 은 정말 편리 하 다.만약 에 우리 가 Person 류 에 선택 할 수 있 는 생년월일 을 추가 하고 싶다 면:

public Person(String firstName, String lastName, LocalDate birthDate) {
    this(firstName, lastName);
    this.birthDate = birthDate;
}
그리고 우 리 는 equals()방법 을 업데이트 해 야 하지만 Null 을 처리 해 야 합 니 다.이 조건 을 equals()방법 에 추가 할 수 있 습 니 다.

birthDate == null ? that.birthDate == null : birthDate.equals(that.birthDate);
그러나 우리 가 클래스 에 null 이 될 수 있 는 필드 를 많이 추가 하면 매우 혼 란 스 러 워 질 수 있 습 니 다.equals()구현 에서 Objects\#equals 방법 을 사용 하여 더욱 간결 하고 가 독성 을 높 였 습 니 다.

Objects.equals(birthDate, that.birthDate);
4.Comparable 인터페이스
비교 논리 도 대상 에 게 정렬 하 는 데 사용 할 수 있다.비교 인 터 페 이 스 를 통 해 우 리 는 한 대상 이 다른 대상 보다 크 고 같 는 지,작은 지 확인 함으로써 대상 간 의 순 서 를 정의 할 수 있다.
Compariable 인 터 페 이 스 는 일반적인 것 입 니 다.하나의 방법 만 compare To()입 니 다.이 방법 은 일반적인 유형의 인 자 를 받 아들 이 고 int 로 돌아 갑 니 다.현재 값 이 인자 보다 작 으 면 마이너스 로 돌아 갑 니 다.만약 그것들 이 같다 면 0 으로 돌아 갑 니 다.그렇지 않 으 면 바로 돌아 갑 니 다.
예 를 들 어 우리 Person 류 에서 우 리 는 Person 대상 의 성씨 에 따라 비교 하고 싶 습 니 다.

public class Person implements Comparable<Person> {
    //...

    @Override
    public int compareTo(Person o) {
        return this.lastName.compareTo(o.lastName);
    }
}
이것 보다 성 이 큰 사람 이 copare To()방법 을 사용 하면 마이너스 int 로 돌아 갑 니 다.성씨 가 같 으 면 0 으로 돌아간다.그렇지 않 으 면 정 int 로 돌아 갑 니 다.
5.Comparator 인터페이스
Comparator 인 터 페 이 스 는 범 형 이 고 compare 방법 이 있 습 니 다.이 방법 은 이 범 형 유형의 두 개의 인 자 를 받 아들 이 고 정 수 를 되 돌려 줍 니 다.우 리 는 앞의 비교 가능 한 인터페이스 에서 이미 이런 모델 을 보 았 다.
비교 기 유사;그러나 클래스 와 의 정 의 는 분리 된다.따라서 우 리 는 하나의 유형 에 대해 여러 개의 비교 기 를 정의 할 수 있 는데 그 중에서 우 리 는 비교 가능 한 실현 만 제공 할 수 있다.
만약 에 우리 가 웹 페이지 에 사람 정 보 를 보 여 주 는 표 가 있다 고 가정 하면 우 리 는 사용자 가 성씨 가 아 닌 이름 으로 그들 을 정렬 할 수 있 도록 하고 싶 습 니 다.만약 우리 가 현재 의 실현 을 유지 하고 싶다 면,Comparable 을 사용 하 는 것 은 불가능 하지만,우 리 는 자신의 비교 기 를 실현 할 수 있다.
Person Comparator 를 만 듭 니 다.이름 에 따라 만 비교 합 니 다.

Comparator<Person> compareByFirstNames = Comparator.comparing(Person::getFirstName);
이제 이 비교 기로 한 그룹의 사람들 을 정렬 합 시다.

Person joe = new Person("Joe", "Portman");
Person allan = new Person("Allan", "Dale");

List<Person> people = new ArrayList<>();
people.add(joe);
people.add(allan);

people.sort(compareByFirstNames);

assertThat(people).containsExactly(allan, joe);
compare To()구현 중 Comparator 인터페이스 에 있 는 다른 방법 을 사용 할 수 있 습 니 다.

@Override
public int compareTo(Person o) {
    return Comparator.comparing(Person::getLastName)
      .thenComparing(Person::getFirstName)
      .thenComparing(Person::getBirthDate, Comparator.nullsLast(Comparator.naturalOrder()))
      .compare(this, o);
}
이런 상황 에서 우 리 는 먼저 성 을 비교 한 후에 이름 을 비교 합 니 다.그리고 우 리 는 생년월일 을 비교 하지만,그것들 은 비어 있 기 때문에,우 리 는 그것 을 어떻게 처리 하 는 지 설명해 야 하기 때문에,우 리 는 두 번 째 파 라미 터 를 제시 하여,그것들의 자연 순서에 따라 비교 해 야 한다 고 알려 주 었 지만,빈 값 은 마지막 이 었 다.
6.Apache Commons 사용
이제 apachecomons 라 이브 러 리 를 보 여 주세요.우선 Maven 의존 항목 을 가 져 옵 니 다.

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.11</version>
</dependency>
6.1 ObjectUtils 의 notEqual 방법
우선 Object Utils\#notEqual 방법 에 대해 토론 합 니 다.그것 은 두 개의 대상 매개 변 수 를 필요 로 하 며,그들의 equals()방법 에 따라 그것들 이 같은 지 확인 해 야 한다.빈 값 도 처리 합 니 다.
문자열 예 시 를 다시 사용 합 니 다:

String a = new String("Hello!");
String b = new String("Hello World!");

assertThat(ObjectUtils.notEqual(a, b)).isTrue();
Object Utils 에는 equals()방법 이 있 습 니 다.그러나 자바 7 에 Objects\#equals 가 등장 한 이후 이런 방법 은 버 려 졌 다.
6.2 ObjectUtils 의 compare 방법
이제 대상 순 서 를 Object Utils\#compare 방법 으로 비교 합 시다.이것 은 범 형 방법 으로 이 범 형 유형의 두 개의 비교 가능 한 파 라 메 터 를 받 아들 이 고 정 수 를 되 돌려 줍 니 다.
문자열 을 어떻게 사용 하 는 지 다시 봅 시다.

String first = new String("Hello!");
String second = new String("How are you?");

assertThat(ObjectUtils.compare(first, second)).isNegative();
기본적으로 이 방법 은 빈 값 을 더 큰 값 으로 보고 빈 값 을 처리 합 니 다.그것 은 이 행 위 를 반전 시 키 고 더 작 게 고려 할 수 있 는 불 파 라 메 터 를 제공 합 니 다.
7.Guava 사용
이제 과 바 를 보 자Guava Google , Google Java , : [collections] 、 [caching] 、 [primitives support] 、 [concurrency libraries] 、 [common annotations] 、 [string processing] I/O 。우선 의존 항목 가 져 오기:

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>29.0-jre</version>
</dependency>
7.1 Objects 의 equal 방법
apache comons 라 이브 러 리 와 유사 하 게 Google 은 두 대상 이 같은 지 확인 하 는 방법 을 제공 합 니 다.objects\#equal.비록 그들 은 서로 다른 실현 이 있 지만,그들 은 같은 결 과 를 되 돌려 준다.

String a = new String("Hello!");
String b = new String("Hello!");

assertThat(Objects.equal(a, b)).isTrue();
deprecated 로 표시 되 지 않 았 음 에 도 불구 하고 이 방법의 자바 독 은 deprecated 로 여 겨 져 야 한다 고 말 했다.자바 7 은 Objects\#equals 방법 을 제공 하기 때문이다.
7.2 Comparison 방법
현재 과 바 쿠 는 두 대상 을 비교 하 는 방법 을 제공 하지 않 았 다.(우 리 는 다음 절 에서 이 점 을 어떻게 실현 하 는 지 볼 것 이다)그러나 그것 은 확실히 원시 적 인 가 치 를 비교 하 는 방법 을 제공 했다.Ints helper 류 의 compare()방법 이 어떻게 작 동 하 는 지 보 여 줍 니 다.

assertThat(Ints.compare(1, 2)).isNegative();
일반적으로 첫 번 째 매개 변수 가 두 번 째 매개 변수 보다 작 거나 같 거나 크 면 하나의 정 수 를 되 돌려 주 고 이 정 수 는 마이너스,0 또는 정 일 수 있다.bytes 를 제외 하고 모든 기원 유형 은 비슷 한 방법 이 있다.
7.3 ComparisonChain 클래스
마지막 으로 Guava 쿠 는 ComparisonChain 류 를 제공 하여 우리 가 일련의 비 교 를 통 해 두 대상 을 비교 할 수 있 도록 해 주 었 다.우 리 는 두 사람의 이름과 성 씨 를 쉽게 비교 할 수 있다.

Person natalie = new Person("Natalie", "Portman");
Person joe = new Person("Joe", "Portman");

int comparisonResult = ComparisonChain.start()
  .compare(natalie.getLastName(), joe.getLastName())
  .compare(natalie.getFirstName(), joe.getFirstName())
  .result();

assertThat(comparisonResult).isPositive();
바 텀 비 교 는 copare To()방법 으로 이 루어 지기 때문에 copare()방법 에 전 달 된 매개 변 수 는 원본 유형 이나 비교 가능 한 대상 이 어야 합 니 다.
8.전체 코드
자바 개체 비교
자바 의 다양한 비교 대상 방식 에 대한 비교 정리 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.자바 비교 대상 에 관 한 더 많은 방식 의 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기