2011-02-14 2 views
5

2 개의 구성 요소가있는 키로 HashMap을 구현하고 싶습니다. 전의. 나는 속도와 컬렉션의 크기를 고려, 자바에서이를 구현하려면 어떻게Java 컬렉션 2 키로

Pseudocode: 

Key = <Component1, Component2> 
CollName<Key, Val> coll = new CollName<Key, Val>; 

. 감사합니다 : 당신이 키

public class CompositeKey<... , ...> { 
    ... component1; 
    ... component2; 

    // getter , setter, ... 

    // equals 

    // hashcode() 
} 

를 보유하고 D 당신은 도우미가 필요

답변

7

(복합 키) 클래스는 다음 키로 사용할 수 있습니다

CompositeKey cKey = new CompositeKey(1,2); 
Map x.put(cKey,val); 

그것은 여기에 매우 중요하다 좋은 방법으로 equals()hashCode()을 구현하십시오. 대부분의 IDE가 여기에서 당신을 도울 수 있습니다. hashCode는 키의 해시 충돌을 방지하기 위해 "고유"값을 반환한다는 점에서 중요합니다 (즉, 상수 값을 반환하면 최악의 경우이므로 모든 값이 동일한 버킷으로 끝납니다). 해시 코드의 많은 구현은 해시 알고리즘에 대해 이야기 어떤 CS 책을 파고,

당신이 세부 사항을 더 원하는 경우
hashcode = component1.hashCode() + 37* component2.hashCode(); 

함께 뭔가.

지속성을 위해 사용하려면 this blog post을보십시오.

+0

@Hieko : Inventive.이 개념에 익숙하지 않은 헬퍼 클래스를 설명하는 소스를 알고 계십니까? –

+1

도우미 클래스는 특별한 개념이 아닙니다. 두 개의 하위 개체를 하나로 묶어 취급하는 일반적인 클래스입니다. 보다 자세한 코드 예제는 아래 예제를 참조하십시오. –

+0

@Hieko 중요한 문제는 equals와 hashcode를 올바르게 구현하는 방법에 있습니다. –

2

두 개의 키로지도를 직접 만들 수는 없지만 둘을 결합 할 수는 있습니다.

가장 간단한 방법은 문자열을 직렬화하여 결합하는 것입니다. 개체를 추정

String key = obj1.toString() + "-" + obj2.toString(); 
myMap.put(key, myValue); 

쉽게 고유 것이다 문자열로 직렬화 할 수 있습니다.

그렇지 않은 경우 래퍼 객체를 만드는 것이 가장 좋습니다. equals() 및 hashCode() 메서드를 재정의하는 객체를 정의해야합니다. 거친 예를

class CombinedKey{ 
    private MyClass object1; 
    private MyClass object2; 

    public CombinedKey(MyClass object1, MyClass object2){ 
     this.object1 = object1; 
     this.object2 = object2; 
    } 
    public int hashCode(){ 
     return object1.hashCode() + object2.hashCode(); 
    } 

    @Override 
    public Boolean equals(Object otherObject){ 
     if(otherObject == null || otherObject.getObject1() == null) return false; 
     return object1.equals(otherObject.getObject1()) && object2.equals(otherObject.getObject2(); 
    } 

    public MyClass getObject1() { return object1; } 
    public MyClass getObject2() { return object2; } 

} 

(당신은 또한 다른 시나리오에서 재사용 할 수 있도록이 클래스를 정의 제네릭 사용을 고려할 수 있음)으로

사용법 :

Map<CombinedKey, Object> myMap = new HashMap<CombinedKey, Object>(); 
myMap.put(new CombinedKey(obj1, obj2), value); 
+3

답에 동의하십시오. 메소드가 equals() 시그니처를 가지므로 Object 클래스에서 오버라이드되지는 않습니다. –

+1

데이터베이스에서 복합 키를 생각 나게합니다. –

+2

키 쌍 (a, b)의 경우이 구현은 해시 충돌을 만드는 (b, a)와 동일한 해시 코드를 반환하므로 성능이 다소 떨어질 수 있습니다. –

0

HashMap의 일반적인 용도입니다. 요점은 정의해야합니다 (재정의) equals()hashCode()Key에 올바르게 있습니다.

1

아직 Google Guava 답변을 찾지 못했기 때문에이를 지적했습니다. Table을 사용하고 싶습니다.

0

CompositKey/Pair/Tuple을 사용하는 좋은 대안은 List를 사용하는 것입니다. List 구현은 이미 equals()hashCode()으로 적절하게 정의되어 있으며 쉽게 만들 수 있습니다. Arrays.asList()