2014-11-18 1 views
7

안녕하세요 당신이 찾고있는 개체에 대한 Hashcode, HashMode HashMap에서 키로 사용하는 일종의 같은 경우 직접 HashSet 내용을 액세스 할 수 있는지 궁금하네요.직접 HashCode를 사용하여 HashSet에 액세스 하시겠습니까? (자바)

나는 그것이 같은 종류의 뭔가를 작동 할 수 상상 :

MyObject object1 = new MyObject(1); 

Set<MyObject> MyHashSet = new HashSet<MyObject>(); 

MyHashSet.add(object1) 

int hash = object1.getHashCode 

MyObject object2 = MyHashSet[hash]??? 

감사합니다!

편집 : 답변 해 주셔서 감사합니다. 좋아, 나는 HashSet의 계약을 조금 추진하고 있을지도 모른다는 것을 이해한다. 그러나이 특정 프로젝트에 대해 평등은 해시 코드에 의해서만 결정되며, hashcode/hashbucket 당 하나의 객체 만 존재한다는 것을 나는 알고있다. HashMap을 사용하기를 꺼려했던 이유는 HashMap이 객체를 키로 사용하기 때문에 Integer 객체로 매핑하는 프리미티브 int를 변환해야하기 때문에 성능에 영향을 미칠 수도 있기 때문입니다. 비슷한 것을 구현하기 위해 할 수있는 일이 있습니까?

+0

아니요, 불가능합니다. 왜 이걸하고 싶니? 네가지도를 원하는 것 같아. –

+2

공개 API가 없습니다. 그리고 해시 코드가 충돌하더라도 여러 객체를 반환 할 수 있습니다. – Thilo

+0

그런 식으로 물건을 얻을 수는 없습니다. 두 개의 다른 객체가 동일한 해시 코드를 가질 수는 있지만 같지 않을 수도 있기 때문에 의미가 있습니다. Hashset은 해시 코드가 일치하면 두 객체를 equals 메소드와 내부적으로 비교합니다. – BatScream

답변

2

HashSet의 일반적인 구현은 HashMap에 의해 뒷받침되므로 다소 번거롭지 않으므로 HashMap을 피할 수 있습니다. 조기 최적화는 모든 악의 뿌리가되는 기초

, 난 당신이 처음에 HashMap를 사용 및 Integer에서 int의 복싱/언 박싱 오버 헤드가 정말 문제가 있다면 당신이 구현해야 (또는 찾을 수 있습니다 제안) 수공 HashSet 비교를 위해 원시 을 사용합니다. 표준 Java 라이브러리는 실제로 복싱/언 박싱 비용을 염려하지 않으려 고합니다. 언어 전체가 성능 문제를 팔아 오래 전에 상당한 이득을 얻었습니다. 요즘 (2004 년 이후!) 언어는 자동으로 상자와 상자에서 "당신은이 정책에 대해 걱정할 필요가 없습니다"라는 것을 알 수 있습니다. 대부분의 경우 그것은 옳습니다.

내가 얼마나 풍부하게 'HashKeyedSet'일 필요가 있는지 모르지만 기본 해시 테이블은 실제로 그렇게 어렵지 않습니다.

0

HashSet은 개체이며 공개 API가 없으므로 불가능합니다. 또한 여러 객체가 동일한 해시 코드를 가질 수 있지만 객체가 다를 수 있습니다.

마지막으로 myArray[<index>] 구문을 사용하여 배열에만 액세스 할 수 있습니다.

2

HashSet은 내부적으로 HashMap으로 뒷받침됩니다.이 질문은 공개 API를 통해 사용할 수 없습니다. 그러나, 우리는 내부지도에 액세스 할 반사를 사용하고 동일한 hashCode와 키 찾기 :

HashSet<String> set = new HashSet<>(); 
set.add("foo"); set.add("bar"); set.add("qux"); 

int hashcode = "qux".hashCode(); 

System.out.println(getFromHashCode(hashcode, set)); 

출력 :

qux 
+0

감사합니다. 그것은 훌륭한 방법입니다. 그러나 for 루프를 사용하여 HashSet을 검색해야합니다. 지금은 불가능하다고 생각하지만, 해시 코드로 직접 데이터를 가져올 수있는 방법이있을 것이라고 생각했습니다. 그것이 목록 또는 무언가 인 것처럼. – Kode47

+0

'HashMap'은 공개 API를 통해 테이블의 특정 인덱스에서 버켓을 가져올 수 없으므로 더 많은 반영 hackery로 일정 시간 내에이 작업을 수행 할 수 있다고 생각합니다. – August

0
예에서 사용

private static <E> E getFromHashCode(final int hashcode, HashSet<E> set) throws Exception { 
    // reflection stuff 
    Field field = set.getClass().getDeclaredField("map"); 
    field.setAccessible(true); 

    // get the internal map 
    @SuppressWarnings("unchecked") 
    Map<E, Object> interalMap = (Map<E, Object>) (field.get(set)); 

    // attempt to find a key with an identical hashcode 
    for (E elem : interalMap.keySet()) { 
     if (elem.hashCode() == hashcode) return elem; 
    } 
    return null; 
} 

리플렉션을 사용하여 HashSet 구현의 내부 데이터 구조에 직접 액세스하는 코드를 쉽게 작성할 수 있습니다. 물론 코드는 코딩 할 특정 JVM의 구현 세부 사항에 따라 달라집니다. 또한 SecurityManager의 제약 조건에 따라 달라질 수 있습니다 (있는 경우).

HashSet의 일반적인 구현은 내부 데이터 구조로 HashMap을 사용합니다. HashMap에는 배열의 인덱스에 매핑 된 키의 해시 코드로 인덱싱되는 배열이 있습니다. 해시 코드 매핑 함수는 구현시 비공개 메소드를 호출하여 사용할 수 있습니다. 소스 코드를 읽고 알아 내야합니다. 올바른 버킷에 도착하면 버킷의 올바른 항목을 (equals을 사용하여) 찾아야합니다.

관련 문제