String.hashCode는 같은 문자열이지만 때로는 다른 값으로 바뀔 수 있습니다
Fluter/Dart에서 프로그램을 개발할 때 맵에서 '같은 문자열이 다른 키로 들어오는 것' 현상을 만났습니다.더 조사해 보면 같은 문자열
String.hashCode이 다른 이유가 무엇인지 알 수 있다.이것저것 여러 가지 이유로 Dart의 가장자리를 밟는 버그가 겹쳤지만 upstream에서 해결됐다.
대략적 실현
문자열을 처리하고 반환할 수 있는 함수는 다음과 같습니다.
String foo(String name) {
return "prefix-${name}";
}
Map에 데이터를 넣는 프로세스:Map data = new Map<String, String>();
String str1 = foo("test");
// ...
// str1 は "prefix-test" という文字列
data[str1] = "value";
Map에서 데이터를 체크 아웃하는 프로세스:String str2 = foo("test");
// str2 は "prefix-test" という文字列
// str1 と同じ
String value = data[str2];
// "value" を期待するが null になる
print(value);
위에서 말한 바와 같이 Map에 대해'동일 문자열'을 사용하여 접근했지만 예상대로 처리되지 않았다.hashCode
Map 대상의 hashCode를 사용하여 저장 위치를 제어한다(여러 언어가 이렇게 이루어졌기 때문에 Dart도 그렇다고 생각한다). 그래서 hashCode는 이상하다. 그래서 다음과 같이'같은 문자열, 다르다hashCode'를 확인했다.print("${str1 == str2}"); // true
print("${str1.hashCode == str2.hashCode}"); // false!!!
통상적인Object.hashCode은'동일성을 나타내는 것'을 토대로 계산된 것이다.이런 상황에서 같은 점은 메모리의 주소도 같다는 점이다.그러나
String,Point,Rect 같은 클래스에서 같은 값이면 같은 값==이 되돌아와true하면 같은 값hashCode으로 처리할 수 있다.따라서 다른 곳에서 생성된 대상==이라도 같은 키String로 사용할 수 있다.이번 문제는 어떤 이유로 같은 값Map이 다른 값String으로 바뀌었기 때문이다.또 이런 현상은 iOS 시뮬레이터 및 실제 기기에서만 발생하며, 안드로이드 시뮬레이터 및 실제 기기에서는 일어나지 않는다.
identityHashCode
상기 코드에서 생략된 부분은 문자열
hashCode에 대한 호출str1의 코드가 있다.호출identityHashCode이 변경identityHashCode의 원인이다.identity HashCode란 무엇입니까?
Returns the identity hash code of
hashCode .Returns the same value as
object if [object] has not overridden[Object.hashCode]. Returns the value that [Object.hashCode] would return
on this object, even if
object.hashCode has been overridden.This hash code is compatible with [identical].
덮어쓰기
hashCode의 클래스 대상에 대해서도 기본 클래스hashCode의 값을 얻을 수 있는 함수다.등치라도 다른 대상이라면 다른 대상으로 처리할 때 이 함수Object.hashCode 또는identityHashCode를 사용한다.그러나 이 함수 내부 호출
identical의 값으로 Object.hashCode의 결과도 캐시되었다.String.hashCode의 계산은 어느 정도의 원가가 필요하기 때문에 계산된 물건은 캐시hashCode가 필요하다면 문제가 된다.일반적으로 코드를 쓰면
String 사용하지 않기 때문에 대부분의 응용 프로그램은 문제가 없을 것이라고 생각합니다.대책
identityHashCode는 더 이상 사용하지 않습니다.이 함수를 사용하지 않아도 가능한 코드는 동일성이라기보다는'동일 여부'를 기반으로 처리돼 이렇게 수정됐다.어쨌든 Flutter가 사용하는Dart의 버전이 상승하고 그에 상응하는 수정이 포함되며 그 전에 대응해야 할 경우 코드를 다시 수정할 수 있다.
덤
원인을 규명하기 전에 시도해 본 일
Reference
이 문제에 관하여(String.hashCode는 같은 문자열이지만 때로는 다른 값으로 바뀔 수 있습니다), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/najeira/articles/2018-08-02-qiita-3558680224c8f226a4b7텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)