TreeSet 클래스 정렬 문제 해결
8171 단어 javaTreeSet 정렬
1. 자연 정렬
TreeSet은 집합 요소의compareTo(Object obj) 방법을 호출하여 요소 간의 크기 관계를 비교한 다음에 집합 요소를 오름차순으로 배열합니다. 이런 방식이 바로 자연 정렬입니다.비교의 전제 조건: 두 객체의 유형은 동일합니다.
java는 Comparable 인터페이스를 제공합니다. 이 인터페이스에compareTo(Object obj) 방법이 정의되어 있습니다. 이 방법은 정수치를 되돌려주고 이 인터페이스를 실현하는 클래스는 반드시 이 방법을 실현해야 합니다. 이 인터페이스를 실현하는 클래스의 대상은 크기를 비교할 수 있습니다.한 대상이 이 방법을 다른 대상과 비교할 때, 예를 들어obj1.comparTo(obj2), 이 방법이 0으로 되돌아오면 이 두 대상이 같다는 것을 나타낸다.정수를 되돌려주면obj1이obj2보다 크다는 것을 나타냅니다.만약 이 방법이 음정수를 되돌려준다면obj1이obj2보다 작다는 것을 나타낸다.
java 상용 클래스는Comparable 인터페이스를 실현하고 비교적 큰 크기의 표준을 제공합니다.Comparable 인터페이스를 위한 일반 클래스:
다음 절차는 오류를 보고합니다.
class Err
{
}
public class TestTreeSetError
{
public static void main(String[] args)
{
TreeSet ts = new TreeSet();
// TreeSet Err
ts.add(new Err());
ts.add(new Err());
}
}
설명:위 프로그램은 TreeSet 집합에 2개의 Err 대상을 추가하려고 합니다. 첫 번째 대상을 추가할 때 TreeSet에 요소가 없기 때문에 문제가 없습니다.두 번째 Err 대상을 추가할 때 TreeSet은 이 대상의compareTo(Object obj) 방법을 호출하여 집합 중의 다른 요소와 비교합니다. 대응하는 클래스가Comparable 인터페이스를 실현하지 못하면 ClassCastException 이상을 일으킬 수 있습니다.그리고 TreeSet에서 원소의 첫 번째 원소를 꺼내려고 할 때 ClassCastException 이상을 일으킬 수 있습니다.
compareTo(Object obj) 방법으로 대상을 비교할 때, 비교 대상인obj의 강제 형식을 같은 형식으로 변환해야 한다. 왜냐하면 같은 종류의 두 실례만 크기를 비교할 수 있기 때문이다.TreeSet에 같은 클래스의 객체를 추가해야 합니다. 그렇지 않으면 ClassCastException 이상을 일으킬 수 있습니다.예를 들어, TreeSet에 문자열 객체를 추가하면 이 작업은 완전히 정상적입니다.두 번째 Date 대상을 추가할 때 TreeSet은 이 대상의compareTo(Object obj) 방법을 호출하여 집합의 다른 요소와 비교합니다. 이때 프로그램은 이상을 일으킬 수 있습니다.
실제 프로그래밍에서 프로그래머는 자신의 클래스가 TreeSet에 여러 종류의 대상을 추가하는 것을 정의할 수 있다. 전제 조건은 사용자 정의 클래스가Comparable 인터페이스를 실현했고 이 인터페이스를 실현할 때compareTo(Object obj) 방법을 실현할 때 강제 형식 변환을 하지 않았다는 것이다.그러나 TreeSet의 집합 데이터를 조작할 때 서로 다른 유형의 요소에 ClassCastExceptio 이상이 발생합니다.(열심히 읽어보면 알 수 있다)
TreeSet 집합에 대상을 추가할 때, TreeSet은 이 대상의compareTo(Object obj) 방법을 사용하여 용기의 다른 대상과 크기를 비교한 다음, 빨간색과 검은색 트리 알고리즘에 따라 저장 위치를 결정합니다.두 객체가compareTo(Object obj)를 통해 비교적 같으면 TreeSet은 같은 위치를 저장한다고 생각합니다.
TreeSet 집합에 있어 두 대상이 같지 않다고 판단하는 기준은 두 대상이 equals 방법을 통해false를 비교적 되돌리거나compareTo(Object obj)를 통해 0을 되돌리지 않았다는 것이다. 설령 두 대상이 같은 대상이라고 하더라도 TreeSet은 그것들을 두 대상으로 삼아 처리한다.
다음 프로그램과 같습니다.
//Z , equals , false,
// compareTo(Object obj) ,
class Z implements Comparable
{
int age;
public Z(int age)
{
this.age = age;
}
public boolean equals(Object obj)
{
return false;
}
public int compareTo(Object obj)
{
return 1;
}
}
public class TestTreeSet
{
public static void main(String[] args)
{
TreeSet set = new TreeSet();
Z z1 = new Z(6);
set.add(z1);
System.out.println(set.add(z1));
// set , 2
System.out.println(set);
// set age
((Z)(set.first())).age = 9;
// set age , 9
System.out.println(((Z)(set.last())).age);
}
}
프로그램 실행 결과:true
[TreeSet.Z@1fb8ee3, TreeSet.Z@1fb8ee3]
구
설명:
프로그램에서 같은 대상을 두 번 추가했습니다. 왜냐하면 z1 대상의 equals () 방법은 항상false를 되돌리고compareTo (Object obj) 방법은 항상 1을 되돌리기 때문입니다.이렇게 하면 TreeSet은 z1 대상과 그 자신도 다르다고 생각하기 때문에 TreeSet에 두 개의 z1 대상을 추가합니다.TreeSet 객체에 저장된 두 요소는 실제로 동일한 요소입니다.그래서 TreeSet 집합의 첫 번째 요소의age 속성을 수정하면 이 TreeSet 집합의 마지막 요소의age 속성도 바뀐다.
요약: 하나의 대상을 TreeSet에 넣어야 할 때, 이 대상이 대응하는 클래스의 equals () 방법을 다시 쓸 때, 이 방법은compareTo (Object obj) 방법과 일치하는 결과를 확보해야 한다. 그 규칙은 두 대상이equals 방법을 통해true를 비교할 때, 이 두 대상은compareTo (Object obj) 방법을 통해compareTo (Object obj) 방법을 비교할 때 0을 되돌려야 한다는 것이다.
만약 두 대상이 equals 방법을 통해true를 비교적 되돌려주지만, 이 두 대상이compareTo(Object obj) 방법을 통해 0을 되돌려 주지 않을 때, 이것은 TreeSet이 이 두 대상을 서로 다른 위치에 저장하여 두 대상을 모두 추가할 수 있게 한다. 이것은 Set 집합의 규칙과 약간 차이가 있다.
만약 두 대상이compareTo(Object obj) 방법을 통해 0을 비교적 되돌려준다면, 이퀄스 방법을 통해false를 비교적 되돌려줄 때 더욱 번거로울 것이다. 두 대상이compareTo(Object obj) 방법을 통해 비교적 같기 때문에, TreeSet은 그것들을 같은 위치에 저장하려고 시도하지만, 실제로는 안 된다. 그렇지 않으면 한 대상만 남게 되기 때문에 처리하기가 비교적 번거롭다.
만약 TreeSet에 가변 대상을 추가한 후 다음 프로그램에서 이 가변 대상의 속성을 수정하여 다른 대상과 크기 순서가 바뀌지만, TreeSet은 순서를 다시 조정하지 않을 뿐만 아니라, 심지어 TreeSet에 이 두 대상을 저장할 수도 있습니다. 이 두 대상은 equals 방법으로 비교하여true,compareTo(Object obj) 방법으로 0을 되돌려줍니다.
다음 프로그램과 같습니다.
class R
{
int count;
public R(int count)
{
this.count = count;
}
public String toString()
{
return "R(count :" + count + ")";
}
public boolean equals(Object obj)
{
if (obj instanceof R)
{
R r = (R)obj;
if (r.count == this.count)
{
return true;
}
}
return false;
}
public int hashCode()
{
return this.count;
}
}
public class TestHashSet2
{
public static void main(String[] args)
{
HashSet hs = new HashSet();
hs.add(new R(5));
hs.add(new R(-3));
hs.add(new R(9));
hs.add(new R(-2));
// TreeSet ,
System.out.println(hs);
//
Iterator it = hs.iterator();
R first = (R)it.next();
// count
first.count = -3;
// count TreeSet
System.out.println(hs);
hs.remove(new R(-3));
System.out.println(hs);
// false
System.out.println("hs count -3 R ?" + hs.contains(new R(-3)));
// false
System.out.println("hs count 5 R ?" + hs.contains(new R(5)));
}
}
프로그램 실행 결과:[R(count 속성: -3), R(count 속성: -2), R(count 속성: 5), R(count 속성: 9)]
[R(count 속성: 20), R(count 속성: -2), R(count 속성: 5), R(count 속성: -2)]
[R(count 속성: 20), R(count 속성: -2), R(count 속성: 5), R(count 속성: -2)]
[R(count 속성: 20), R(count 속성: -2), R(count 속성: -2)]
설명:
위 프로그램의 R 대상은 정상적으로 equals 방법과comparable 방법 종류를 다시 썼는데 이 두 가지 방법은 모두 R 대상의count 속성을 판단의 근거로 한다.프로그램의 첫 번째 출력 결과가 질서정연하게 배열된 것을 볼 수 있다.R 대상의 count 속성을 바꾸면 프로그램의 출력 결과도 바뀌고 중복 요소도 포함됩니다.TreeSet 집합에 있는 가변 요소의 속성이 바뀌면 다시 보기에서 대상을 삭제할 때 TreeSet도 삭제에 실패합니다. (심지어 집합에 있는 속성은 수정되지 않았지만 수정된 요소와 같은 요소도 삭제할 수 없습니다.)
-2인 R 객체는 삭제된 요소가 없습니다.프로그램은count가 5인 R 대상을 삭제할 수 있습니다. 이것은 TreeSet이 수정된 속성이 없고 수정된 다른 대상과 중복되지 않은 대상을 삭제할 수 있음을 나타냅니다.
요약: 이러한 객체를 처리하는 데 HashSet과 관련된 작업은 매우 복잡하고 오류가 발생하기 쉽습니다.프로그램을 더욱 튼튼하게 하기 위해 HashSet과 TreeSet 집합에 변하지 않는 대상만 넣는 것을 추천합니다.
2. 정렬 사용자 정의
TreeSet의 자연 정렬은 집합 요소의 크기에 따라 TreeSet이 그들을 오름차순으로 정렬합니다.내림차순 같은 사용자 정의 정렬이 필요한 경우 Comparator 인터페이스를 사용할 수 있습니다.이 인터페이스에는 intcompare(T o1, T o2) 방법이 포함되어 있으며, 이 방법은 o1과 o2의 크기를 비교하는 데 사용됩니다.
사용자 정의 정렬이 필요하면 TreeSet 집합 대상을 만들 때 Comparator 대상이 이 TreeSet 집합과 연결되고 이 Comparator 대상이 집합 요소의 정렬 논리를 책임집니다.
다음 프로그램과 같습니다.
class M {
int age;
public M(int age) {
this.age = age;
}
public String toString() {
return "M (age:" + age + ")";
}
}
public class TestTreeSet3 {
public static void main(String[] args) {
TreeSet ts = new TreeSet(new Comparator() {
public int compare(Object o1, Object o2) {
M m1 = (M) o1;
M m2 = (M) o2;
if (m1.age > m2.age) {
return -1;
} else if (m1.age == m2.age) {
return 0;
} else {
return 1;
}
}
});
ts.add(new M(5));
ts.add(new M(-3));
ts.add(new M(9));
System.out.println(ts);
}
}
프로그램 실행 결과:[M 객체(age:9), M 객체(age:5), M 객체(age:-3)]
설명:
위 프로그램에서Comparator 인터페이스의 익명 내부 클래스 대상을 만들었습니다. 이 대상은ts 집합의 정렬을 책임집니다.따라서 우리가 ts 집합에 M 대상을 추가할 때 M 클래스가 Comparable 인터페이스를 실현할 필요가 없다. 왜냐하면 이때 TreeSet은 M 대상을 통해 크기를 비교할 필요가 없고 TreeSet과 관련된Comparator 대상이 집합 요소의 정렬을 책임지기 때문이다.사용자 정의 정렬을 사용할 때, TreeSet은 집합 요소를 정렬할 때 집합 요소 자체의 크기에 관계없이 Comparator 대상이 집합 요소의 정렬 규칙을 책임집니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
38. Java의 Leetcode 솔루션텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.