특정 객체를 HashMap에 저장하려고합니다. 문제는 대개 단일 객체를 키로 사용한다는 것입니다. 예를 들어, String을 사용할 수 있습니다. 여러 객체를 사용하려면 어떻게해야합니까? 예를 들어, 클래스와 문자열. 거기에 구현하는 간단하고 깨끗한 방법이 있습니까?두 개 이상의 객체를 HashMap 키로 사용하기
답변
당신 키의 해시 코드를 구현하고 동일해야합니다. 그것은 의 SortedMap 경우, 그것은 또한 Comparable 인터페이스를 구현해야한다
public class MyKey implements Comparable<MyKey>
{
private Integer i;
private String s;
public MyKey(Integer i,String s)
{
this.i=i;
this.s=s;
}
public Integer getI() { return i;}
public String getS() { return s;}
@Override
public int hashcode()
{
return i.hashcode()+31*s.hashcode();
}
@Override
public boolean equals(Object o)
{
if(o==this) return true;
if(o==null || !(o instanceof MyKey)) return false;
MyKey cp= MyKey.class.cast(o);
return i.equals(cp.i) && s.equals(cp.s);
}
public int compareTo(MyKey cp)
{
if(cp==this) return 0;
int i= i.compareTo(cp.i);
if(i!=0) return i;
return s.compareTo(cp.s);
}
@Override
public String toString()
{
return "("+i+";"+s+")";
}
}
public Map<MyKey,String> map= new HashMap<MyKey,String>();
map.put(new MyKey(1,"Hello"),"world");
나는 당신이 열쇠로 사용할 클래스와 문자열을 포함 홀더 클래스를 만들 수있는 목록을
map.put(Arrays.asList(keyClass, keyString), value)
를 사용하는 경향이있다.
public class Key {
public MyClass key_class;
public String key_string;
public Key(){
key_class = new MyClass();
key_string = "";
}
}
아마도 가장 좋은 해결책은 아니지만 가능성이 있습니다.
키로 사용되는 모든 클래스는 equals() 및 hashCode()를 제대로 재정의해야합니다. – notnoop
나는 접근법을 좋아하지만, 해시 코드와 equals 메소드를 추가하는 것은 유스 케이스의 필수 사항이다. 나는 또한 그것을 불변의 것으로 만들 것이다. –
@msaeed와 @Jens Schauder, 포인터에 감사드립니다. –
내가 아는 가장 쉬운 방법은 래퍼 클래스를 만들고 hashmap 및 equals를 재정의하는 것입니다. 예를 들어 : 물론
public class KeyClass {
private String element1;
private String element2;
//boilerplate code here
@Override
public boolean equals(Object obj) {
if (obj instanceof KeyClass) {
return element1.equals(((KeyClass)obj).element1) &&
element2.equals(((KeyClass)obj).element2);
}
return false;
}
@Override
public int hashCode() {
return (element1 + element2).hashcode();
}
}
, 나는함으로써 당신의 여러 키에 해시와 평등 검사를 허용하는 StringBuilder에 및 어떤 다른,하지만 당신은 등호 및 해시 코드를 오버라이드 (override) 한이 방법을 사용하는 것이 좋습니다 것입니다.
또한 개체를 안전을 위해 불변 (편집 할 수 없음)로 만들 것을 권장하지만 이는 전적으로 환경 설정입니다.
오브젝트가 두 개의 키 또는 두 가지 키로 구성된다는 것을 의미합니까?
첫 번째 경우를 원한다면. 즉, 두 개의 키, 즉 클래스 또는 객체에 의해 키잉 된 객체는 두 개의 맵을 사용해야합니다.
Map<Key1, value>
Map<Key2, value>
는 두 번째 경우에는 그렇게,지도의지도가 필요합니다
Map<Key1, Map<Key2, value>>
아파치 코 몬즈 컬렉션은 당신을 위해 트릭을 할 수있는 multikey지도가 있습니다
그것처럼 보이는을 최대 5 개의 "키"를 처리합니다.
다른 사람들이 "핵심"수업을 만들 것을 제안하는 곳이 몇 군데 있습니다. 전적으로 동의합니다. 그냥 도움이되는 힌트를 추가한다고 생각했습니다.
eclipse 또는 netbeans를 사용하는 경우 좋은 옵션이 있습니다. Eclipse에 하나 이상의 멤버를 기반으로하는 equals 및 hashcode 메소드를 생성하도록 지정할 수 있습니다. 따라서 검색하려는 멤버 (또는 멤버) 만 선택하면 NB가 작성해야하는 대부분의 코드를 만듭니다.
물론 하나의 객체 만 검색하려는 경우 해시 코드와 equals 메소드를 해당 객체에 위임합니다 (equals 위임은 문제가 될 수 있습니다. 이는 "키 홀더"클래스 중 하나가 객체에이 열쇠입니다, 그러나 그것은 아주 쉽게 고정 (그리고 보통 어쨌든 아무 영향을주지 것입니다) 그래서 내 머리 위로 떨어져
을한다 : 모든 작업이 완료
class KeyHolder {
public final String key;
public final Object storeMe;
public KeyHolder(String key, Object storeMe) {
this.key=key;
this.storeMe=storeMe;
}
public equals(Object o) {
return (o instanceof KeyHolder && ((KeyHolder)o).key.equals(key));
}
public hashcode() {
return key.hashCode();
}
}
하고, 이클립스가 물어 보면 마지막 두 가지를 할 것입니다.
그건 그렇고, 내가 공공 회원을 가지고 있다는 것을 알고, 공개 최종 회원은 게터를 가지고있는 것과 똑같습니다 - 정말 끔찍한 아이디어는 아닙니다. 최근에 이와 같은 작은 유틸리티 클래스에서이 패턴을 사용하기 시작했습니다. 회원이 결승전이 아니라면 세터 (요즘 피하려고하는 것)와 같을 것이므로 악화 될 것입니다.
하나는 아파치의 commons 컬렉션 lib의 MultiKey
class을 사용하여이 문제를 해결할 수 있습니다. 다음은 간단한 예입니다.
import org.apache.commons.collections.keyvalue.MultiKey;
HashMap map = new HashMap();
MultiKey multiKey = new MultiKey(key1, key2);
map.put(multikey,value);
//to get
map.get(new MultiKey(key1,key2));
예를 들어 설명 했음에도 불구하고 [Clay 's answer] (http://stackoverflow.com/a/1190244/157247)와 중복됩니다. –
해당 목록에 대한 Array.asList의 해시 코드가 아닌가요? –
아니요,'List' (또는 Arrays.asList가있는 적어도 모든 AbstractList)의 해시 코드는 해당 요소의 해시 코드에 의해 결정됩니다. 나는 똑같은 생각을했기 때문에 나는 그것을 보았다. –
쉽게 할 수는 있지만 목록에 속한 것을 문서화하지 않는 단점이 있습니다. 그것이 클래스였습니까? 또는 문자열 먼저? 또는 클래스 이름과 문자열? –