목차
* equals(Object) 메소드에 따라 비교합니다. 두 객체가 동일한 경우 두 객체에 대해 hashCode 메소드를 호출하면 동일한 결과가 생성되어야 합니다. HashCode* equals(Object) 메소드에 따르면 두 객체가 동일하지 않은 경우 두 객체에 대해 hashCode 메소드를 호출해도 반드시 다른 정수 결과가 생성되는 것은 아닙니다. 그러나
一致性
性能
碰撞
计算Hsah
总结
Java java지도 시간 Java에서 hashCode 메소드를 구현하기 위한 샘플 코드 공유

Java에서 hashCode 메소드를 구현하기 위한 샘플 코드 공유

Mar 28, 2017 am 10:47 AM

객체 의 고유한 정체성은 단지 좋은 등호를 작성하는 것만으로는 될 수 없다는 것을 알고 계실 것입니다.

을 구현하는 것도 좋지만 이제 hash코드 방법도 구현해야 합니다. 🎜>

Equality와 Hash를 올바르게 수행하는 방법을 살펴보겠습니다. 코드

평등은 일반적인 관점에서 볼 때 해시 코드는 더 기술적이며 이해하기 어려운 경우 성능 향상을 위한 구현 세부 사항일 뿐이라고 할 수 있습니다.

대부분의 데이터입니다. 구조체는 요소가 포함되어 있는지 확인하기 위해 equals 메소드를 사용합니다. 예:

List<String> list = Arrays.asList("a", "b", "c");
boolean contains = list.contains("b");
로그인 후 복사

변수

에는 "b"가 동일한 인스턴스가 아니지만 결과가 포함됩니다. 문자열 상주),

의 각 요소를 비교한 다음 비교 결과를 에 할당하면 동일합니다. 비록 전체 클래스 데이터 구조가 성능 향상을 위해 최적화되었지만

포함된 인스턴스를 비교하는 대신 단축 방법(잠재적인 인스턴스 동일성을 줄임)을 사용하여 비교를 수행합니다. 단축 비교는 다음 측면만 비교하면 됩니다. contains

단축 비교는 인스턴스를 비교하는 것입니다. 동일한 해시 코드를 가진 인스턴스는 반드시 동일하지는 않지만 동일한 인스턴스는 동일한 해시 값을 가져야 합니다. 이러한 데이터 구조는 종종 이 기술을 사용하여 명명됩니다. ,

로 식별할 수 있는데, 그중

가 가장 유명한데요.

Hash보통은 HashMap

요소가 추가되면 해당 해시 코드는 내부
    배열
  • 인덱스

    (소위 버킷)를 계산하는 데 사용됩니다. 즉, 동일하지 않은 요소는 동일한 해시 코드를 가지며 동일한 버킷에 저장되고 함께 묶입니다. 예를 들어 목록에 추가하면
  • 에 대한 인스턴스가 제공됩니다. 해당 해시 코드를 사용하여 버킷 값(인덱스 값)을 계산하며 해당 인덱스 값에 요소가 있는 경우에만 인스턴스를 비교합니다. /wiki/60.html" target="_blank">객체
  • 클래스

    contains해싱의 개념

을 바로가기로 사용하는 경우 동등성을 결정한 다음 우리가 신경써야 할 것은 단 하나입니다: 동일한 객체는 동일한 해시 코드를 가져야 합니다. 이것이

메서드를 재정의하는 경우 일치하는 equals 구현을 만들어야 하는 이유입니다! 🎜>hashCode 그렇지 않으면 동일한 객체가 <a href="http://www.php.cn/wiki/60.html" target="_blank">Object</a>의 기본 구현을 호출하기 때문에 동일한 해시 코드를 갖지 않을 수 있습니다.

지침

hashCodeequals인용hashCode공식 문서

Object&#39;shashCode 일반 규칙:

* 호출 실행 Java 애플리케이션 동일 객체의 경우 hashCode 메서드는 항상 동일한 정수를 반환해야 합니다. 이 정수는 다양한 Java 애플리케이션에서 일관될 필요가 없습니다.

* equals(Object) 메소드에 따라 비교합니다. 두 객체가 동일한 경우 두 객체에 대해 hashCode 메소드를 호출하면 동일한 결과가 생성되어야 합니다. HashCode* equals(Object) 메소드에 따르면 두 객체가 동일하지 않은 경우 두 객체에 대해 hashCode 메소드를 호출해도 반드시 다른 정수 결과가 생성되는 것은 아닙니다. 그러나

프로그래머

는 동일하지 않은 객체에 대해 서로 다른 정수 결과를 생성하면 잠재적으로 해시 테이블 성능이 향상된다는 점을 인식해야 합니다.

첫 번째 점은 동등 일관성
속성

을 반영하고, 두 번째 점은 위에서 만든 요구 사항입니다. 세 번째는 나중에 논의할 중요한 세부 사항을 보여줍니다.

HashCode 구현
다음은

@Override
public int hashCode() {
    return Objects.hash(firstName, lastName);
}
로그인 후 복사
person의 여러 필드를 결합하여 해시 코드를 계산하는 매우 간단한 구현입니다. 모두

함수

를 통해 계산됩니다.

필드 선택

Person.hashCode그러나 어떤 필드가 관련되어 있습니까? 요구 사항은 다음 질문에 답하는 데 도움이 됩니다. 동일한 개체가 동일한 해시 코드를 가져야 하는 경우 해시 코드 계산은 사용되지 않습니다. 동등성 검사가 포함되어야 합니다. (그렇지 않으면 두 개체가 해당 필드에서만 다르지만 여전히 동일할 수 있습니다. 이 경우 두 개체의 해시 코드가 달라집니다.)

그래서 해시 그룹 필드를 사용해야 할 때 사용됩니다. 필드의 하위 집합입니다. 기본적으로 둘 다 동일한 필드를 사용하지만 고려해야 할 몇 가지 세부 사항이 있습니다. Object

一致性

首先,有一致性的要求。它应该相当严格。虽然它允许如果一些字段改变对应的哈希码发生变化(对于可变的类是不可避免的),但是哈希数据结构并不是为这种场景准备的。

正如我们以上所见的哈希码用于确定元素的桶。但如果hash-relevant字段发生了改变,并不会重新计算哈希码、也不会更新内部数组。

这意味着以后通过相等的对象,甚至同一实例进行查询也会失败,数据结构计算当前的哈希码与之前存储实例计算的哈希码并不一致,并是错误的桶。

结论:最好不要使用可变字段计算哈希码!

性能

哈希码最终计算的频率与可能调用equals差不多,那么这里将是影响性能的关键部分,因此考虑此部分性能也是非常有意义的。并且与equals相比,优化之后又更大的上升空间。

除非使用非常复杂的算法或者涉及非常多的字段,那么计算哈希码的运算成本是微不足道的、同样也是不可避免的。但是也应该考虑是否需要包含所有的字段来进行运算。集合需要特别警惕的对待。以Listssets为例,将会包含集合里面的每一个元素来计算哈希码。是否需要调用它们需要具体情况具体分析。

如果性能是至关重要的,使用Objects.hash因为需要为varargs创建一个数组也许并不是最好的选择。但一般规则优化是适用的:不要过早地使用一个通用的散列码算法,也许需要放弃集合,只有优化分析显示潜在的改进。

碰撞

总是关注性能,这个实现怎么呢?

@Override
public int hashCode() {
    return 0;
}
로그인 후 복사

快是肯定的。相等的对象将具有相同的哈希码。并且,没有可变的字段!

但是,我们之前说过的桶呢?!这种方式下所有的实例将会有相同的桶!这将会导致一个链表来包含所有的元素,这样一来将会有非常差的性能。每次调用contains将会触发对整个list线性扫描。

我们希望尽可能少的元素在同一个桶!一个算法返回变化多端的哈希码,即使对于非常相似的对象,是一个好的开始。

怎样才能达到上面的效果部分取决于选取的字段,我们在计算中包含更多的细节,越有可能获取到不同的哈希码。注意:这个与我们所说的性能是完全相反的。因此,有趣的是,使用过多或者过少的字段都会导致糟糕的性能。

防止碰撞的另一部分是使用实际计算散列的算法。

计算Hsah

最简单的方法来计算一个字段的哈希码是通过直接调用hashCode,结合的话会自动完成。常见的算法是首先在以任意数量的数值(通常是基本数据类型)反复进行相乘操作再与字段哈希码相加

int prime = 31;
int result = 1;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
로그인 후 복사

这可能导致溢出,但是不是特别有问题的,因为他们并没有产生Java异常。

注意,即使是非常良好的的哈希算法也可能因为输入特定的模式的数据有导致频繁碰撞。作为一个简单的例子假设我们会计算点的散列通过增加他们的x和y坐标。当我们处理f(x) = -x线上的点时,线上的点都满足:x + y == 0,将会有大量的碰撞。

但是:我们可以使用一个通用的算法,只到分析表明并不正确,才需要对哈希算法进行修改。

总结

我们了解到计算哈希码就是压缩相等的一个整数值:相等的对象必须有相同的哈希码,而出于对性能的考虑:最好是尽可能少的不相等的对象共享相同的哈希码。

这就意味着如果重写了equals方法,那么就必须重写hashCode方法

当实现hashCode

  • 使用与equals中使用的相同的字段(或者equals中使用字段的子集)

  • 最好不要包含可变的字段。

  • 对集合不要考虑调用hashCode

  • 如果没有特殊的输入特定的模式,尽量采用通用的哈希算法

记住hashCode性能,所以除非分析表明必要性,否则不要浪费太多的精力。


위 내용은 Java에서 hashCode 메소드를 구현하기 위한 샘플 코드 공유의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌
Will R.E.P.O. 크로스 플레이가 있습니까?
1 몇 달 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

자바의 완전수 자바의 완전수 Aug 30, 2024 pm 04:28 PM

Java의 완전수 가이드. 여기서는 정의, Java에서 완전 숫자를 확인하는 방법, 코드 구현 예제에 대해 논의합니다.

자바의 웨카 자바의 웨카 Aug 30, 2024 pm 04:28 PM

Java의 Weka 가이드. 여기에서는 소개, weka java 사용 방법, 플랫폼 유형 및 장점을 예제와 함께 설명합니다.

Java의 스미스 번호 Java의 스미스 번호 Aug 30, 2024 pm 04:28 PM

Java의 Smith Number 가이드. 여기서는 정의, Java에서 스미스 번호를 확인하는 방법에 대해 논의합니다. 코드 구현의 예.

Java Spring 인터뷰 질문 Java Spring 인터뷰 질문 Aug 30, 2024 pm 04:29 PM

이 기사에서는 가장 많이 묻는 Java Spring 면접 질문과 자세한 답변을 보관했습니다. 그래야 면접에 합격할 수 있습니다.

Java 8 Stream foreach에서 나누거나 돌아 오시겠습니까? Java 8 Stream foreach에서 나누거나 돌아 오시겠습니까? Feb 07, 2025 pm 12:09 PM

Java 8은 스트림 API를 소개하여 데이터 컬렉션을 처리하는 강력하고 표현적인 방법을 제공합니다. 그러나 스트림을 사용할 때 일반적인 질문은 다음과 같은 것입니다. 기존 루프는 조기 중단 또는 반환을 허용하지만 스트림의 Foreach 메소드는이 방법을 직접 지원하지 않습니다. 이 기사는 이유를 설명하고 스트림 처리 시스템에서 조기 종료를 구현하기위한 대체 방법을 탐색합니다. 추가 읽기 : Java Stream API 개선 스트림 foreach를 이해하십시오 Foreach 메소드는 스트림의 각 요소에서 하나의 작업을 수행하는 터미널 작동입니다. 디자인 의도입니다

Java의 날짜까지의 타임스탬프 Java의 날짜까지의 타임스탬프 Aug 30, 2024 pm 04:28 PM

Java의 TimeStamp to Date 안내. 여기서는 소개와 예제와 함께 Java에서 타임스탬프를 날짜로 변환하는 방법에 대해서도 설명합니다.

캡슐의 양을 찾기위한 Java 프로그램 캡슐의 양을 찾기위한 Java 프로그램 Feb 07, 2025 am 11:37 AM

캡슐은 3 차원 기하학적 그림이며, 양쪽 끝에 실린더와 반구로 구성됩니다. 캡슐의 부피는 실린더의 부피와 양쪽 끝에 반구의 부피를 첨가하여 계산할 수 있습니다. 이 튜토리얼은 다른 방법을 사용하여 Java에서 주어진 캡슐의 부피를 계산하는 방법에 대해 논의합니다. 캡슐 볼륨 공식 캡슐 볼륨에 대한 공식은 다음과 같습니다. 캡슐 부피 = 원통형 볼륨 2 반구 볼륨 안에, R : 반구의 반경. H : 실린더의 높이 (반구 제외). 예 1 입력하다 반경 = 5 단위 높이 = 10 단위 산출 볼륨 = 1570.8 입방 단위 설명하다 공식을 사용하여 볼륨 계산 : 부피 = π × r2 × h (4

Spring Tool Suite에서 첫 번째 Spring Boot 응용 프로그램을 실행하는 방법은 무엇입니까? Spring Tool Suite에서 첫 번째 Spring Boot 응용 프로그램을 실행하는 방법은 무엇입니까? Feb 07, 2025 pm 12:11 PM

Spring Boot는 강력하고 확장 가능하며 생산 가능한 Java 응용 프로그램의 생성을 단순화하여 Java 개발에 혁명을 일으킨다. Spring Ecosystem에 내재 된 "구성에 대한 협약"접근 방식은 수동 설정, Allo를 최소화합니다.

See all articles