Java의 목록에는 반복되는 요소(해시 코드 및 등호)가 포함될 수 있으므로 목록을 중복 제거하는 방법에는 두 가지가 있습니다.
옵션 1: HashSet을 통해 구현할 수 있습니다. 코드는 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다 .
수업 학생 {
개인 문자열 ID;
개인 문자열 이름;
public Student(문자열 ID, 문자열 이름) {
감독자();
this.id = 아이디;
this.name = 이름;
}
@보수
공개 문자열 toString() {
return "학생 [id=" + id + ", 이름=" + 이름 + "]";
}
@보수
공개 int hashCode() {
최종 정수 소수 = 31;
정수 결과 = 1;
결과 = 소수 * 결과 + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
결과 반환;
}
@보수
공개 부울 같음(객체 obj) {
if (this == obj) {
사실을 반환;
}
if (obj == null) {
거짓을 반환;
}
if (getClass() != obj.getClass()) {
거짓을 반환;
}
학생 기타 = (학생) obj;
if (id == null) {
if (other.id != null) {
거짓을 반환;
}
} else if (!id.equals(other.id)) {
거짓을 반환;
}
if (이름 == null) {
if (other.name != null) {
거짓을 반환;
}
} else if (!name.equals(other.name)) {
거짓을 반환;
}
사실을 반환;
}
}
hashCode와 equals라는 두 가지 메소드를 구현해야 합니다. 특정 연산 코드를 다음과 같이 구현해야 하는 이유를 잠시 후에 살펴보겠습니다.
다음과 같이 코드 코드를 복사합니다 .
개인 정적 무효 제거ListDuplicateObject() {
List<Student> list = new ArrayList<Student>();
for (int i = 0; i < 10; i++) {
학생 학생 = new Student("id", "이름");
list.add(학생);
}
System.out.println(Arrays.toString(list.toArray()));
Set<Student> set = new HashSet<Student>();
set.addAll(목록);
System.out.println(Arrays.toString(set.toArray()));
list.removeAll(list);
set.removeAll(세트);
System.out.println(Arrays.toString(list.toArray()));
System.out.println(Arrays.toString(set.toArray()));
}
호출 코드:
다음과 같이 코드 코드를 복사합니다 .
공개 정적 무효 메인(String[] args) {
RemoveListDuplicateObject();
}
HashSet을 사용하여 중복 제거 작업을 수행할 때 hashCode 및 equals 메서드를 재정의해야 하는 이유는 무엇입니까?
HashSet의 추가 작업 소스 코드를 다음과 같이 확인해 보겠습니다.
다음과 같이 코드 코드를 복사합니다 .
공개 부울 추가(E e) {
return map.put(e, PRESENT)==null;
}
HashMap이 작업을 위해 호출됩니다. HashMap의 put 작업을 살펴보겠습니다.
다음과 같이 코드 코드를 복사합니다 .
공개 V put(K 키, V 값) {
if (키 == null)
return putForNullKey(값);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = 테이블[i]; e != null; e = e.next) {
객체 k;
if (e.hash == hash && ((k = e.key) == 키 || key.equals(k))) {
V oldValue = e.value;
e.값 = 값;
e.recordAccess(this);
oldValue를 반환합니다.
}
}
모드카운트++;
addEntry(해시, 키, 값, i);
null을 반환;
}
참고할 사항은 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다 .
if (e.hash == hash && ((k = e.key) == 키 || key.equals(k))) {
...
}
즉, 해시 코드는 동일하고 동일(==)입니다.
복잡성: 한쪽으로만 통과, O(n)
옵션 2: 목록을 직접 탐색하고 포함 및 추가 작업을 구현합니다. 코드는 다음과 같습니다.
다음과 같이 코드 코드를 복사합니다 .
개인 정적 무효 제거ListDuplicateObjectByList() {
List<Student> list = new ArrayList<Student>();
for (int i = 0; i < 10; i++) {
학생 학생 = new Student("id", "이름");
list.add(학생);
}
System.out.println(Arrays.toString(list.toArray()));
List<Student> listUniq = new ArrayList<Student>();
for (학생 학생 : 목록) {
if (!listUniq.contains(학생)) {
listUniq.add(학생);
}
}
System.out.println(Arrays.toString(listUniq.toArray()));
list.removeAll(list);
listUniq.removeAll(listUniq);
System.out.println(Arrays.toString(list.toArray()));
System.out.println(Arrays.toString(listUniq.toArray()));
}
그 외는 위와 동일합니다.
복잡성:
순회하는 동안 다음과 같이 포함 메소드가 호출됩니다.
다음과 같이 코드 코드를 복사합니다 .
공개 부울 포함(객체 o) {
return indexOf(o) >= 0;
}
공개 int indexOf(객체 o) {
if (o == null) {
for (int i = 0; i < 크기; i++)
if (요소데이터[i]==null)
내가 반환;
} 또 다른 {
for (int i = 0; i < 크기; i++)
if (o.equals(elementData[i]))
내가 반환;
}
-1을 반환합니다.
}
새로운 목록에 또 다른 순회 작업이 수행된 것을 확인할 수 있습니다. 즉, 1+2+....+n, 복잡도는 O(n*n)입니다.
결론적으로:
솔루션 1은 매우 효율적입니다. 즉, HashSet을 사용하여 중복 제거 작업을 수행하는 것입니다.