답변:
Java API에는 이러한 클래스가 없습니다. 원하는 Apache Commons 클래스는 BidiMap 구현 중 하나가 될 것입니다 .
수학자로서 저는 이런 종류의 구조를 bijection이라고 부를 것입니다.
다음은이 작업을 수행하는 데 사용한 간단한 클래스입니다 (아직 다른 타사 종속성을 갖고 싶지 않았습니다). 지도에서 사용할 수있는 모든 기능을 제공하지는 않지만 좋은 시작입니다.
public class BidirectionalMap<KeyType, ValueType>{
private Map<KeyType, ValueType> keyToValueMap = new ConcurrentHashMap<KeyType, ValueType>();
private Map<ValueType, KeyType> valueToKeyMap = new ConcurrentHashMap<ValueType, KeyType>();
synchronized public void put(KeyType key, ValueType value){
keyToValueMap.put(key, value);
valueToKeyMap.put(value, key);
}
synchronized public ValueType removeByKey(KeyType key){
ValueType removedValue = keyToValueMap.remove(key);
valueToKeyMap.remove(removedValue);
return removedValue;
}
synchronized public KeyType removeByValue(ValueType value){
KeyType removedKey = valueToKeyMap.remove(value);
keyToValueMap.remove(removedKey);
return removedKey;
}
public boolean containsKey(KeyType key){
return keyToValueMap.containsKey(key);
}
public boolean containsValue(ValueType value){
return keyToValueMap.containsValue(value);
}
public KeyType getKey(ValueType value){
return valueToKeyMap.get(value);
}
public ValueType get(KeyType key){
return keyToValueMap.get(key);
}
}
충돌이 발생하지 않으면 항상 동일한 HashMap에 양방향을 추가 할 수 있습니다. :-)
GETah의 답변에 영감을 받아 몇 가지 개선 사항을 통해 비슷한 것을 작성하기로 결정했습니다.
Map<K,V>
-Interface를 구현하고 있습니다.put
(적어도 이로써 보증하고 싶습니다).사용법은 매핑 호출에 대한 역보기를 얻기 위해 노멀 맵과 같습니다 getReverseView()
. 콘텐츠는 복사되지 않고보기 만 반환됩니다.
이것이 완전히 어리석은 것인지 확신 할 수 없습니다 (실제로는 그렇지 않을 것입니다). 결함이 발견되면 댓글을 남겨 주시면 답변을 업데이트하겠습니다.
public class BidirectionalMap<Key, Value> implements Map<Key, Value> {
private final Map<Key, Value> map;
private final Map<Value, Key> revMap;
public BidirectionalMap() {
this(16, 0.75f);
}
public BidirectionalMap(int initialCapacity) {
this(initialCapacity, 0.75f);
}
public BidirectionalMap(int initialCapacity, float loadFactor) {
this.map = new HashMap<>(initialCapacity, loadFactor);
this.revMap = new HashMap<>(initialCapacity, loadFactor);
}
private BidirectionalMap(Map<Key, Value> map, Map<Value, Key> reverseMap) {
this.map = map;
this.revMap = reverseMap;
}
@Override
public void clear() {
map.clear();
revMap.clear();
}
@Override
public boolean containsKey(Object key) {
return map.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return revMap.containsKey(value);
}
@Override
public Set<java.util.Map.Entry<Key, Value>> entrySet() {
return Collections.unmodifiableSet(map.entrySet());
}
@Override
public boolean isEmpty() {
return map.isEmpty();
}
@Override
public Set<Key> keySet() {
return Collections.unmodifiableSet(map.keySet());
}
@Override
public void putAll(Map<? extends Key, ? extends Value> m) {
m.entrySet().forEach(e -> put(e.getKey(), e.getValue()));
}
@Override
public int size() {
return map.size();
}
@Override
public Collection<Value> values() {
return Collections.unmodifiableCollection(map.values());
}
@Override
public Value get(Object key) {
return map.get(key);
}
@Override
public Value put(Key key, Value value) {
Value v = remove(key);
getReverseView().remove(value);
map.put(key, value);
revMap.put(value, key);
return v;
}
public Map<Value, Key> getReverseView() {
return new BidirectionalMap<>(revMap, map);
}
@Override
public Value remove(Object key) {
if (containsKey(key)) {
Value v = map.remove(key);
revMap.remove(v);
return v;
} else {
return null;
}
}
}
여기에는 꽤 오래된 질문이 있지만, 제가 방금했던 것처럼 다른 사람이 뇌 차단을해서 우연히 발견하면 도움이 될 것입니다.
나도 양방향 HashMap을 찾고 있었는데, 때로는 가장 유용한 답변 중 가장 간단한 답변입니다.
바퀴를 재발 명하고 싶지 않고 다른 라이브러리 나 프로젝트를 프로젝트에 추가하지 않으려면 병렬 배열 (또는 디자인에서 요구하는 경우 ArrayLists)을 간단하게 구현하는 것이 좋습니다.
SomeType[] keys1 = new SomeType[NUM_PAIRS];
OtherType[] keys2 = new OtherType[NUM_PAIRS];
두 키 중 하나의 색인을 알게되면 다른 키를 쉽게 요청할 수 있습니다. 따라서 조회 방법은 다음과 같습니다.
SomeType getKey1(OtherType ot);
SomeType getKey1ByIndex(int key2Idx);
OtherType getKey2(SomeType st);
OtherType getKey2ByIndex(int key2Idx);
이것은 당신이 적절한 객체 지향 구조를 사용하고 있다고 가정하고, 메소드 만이 이러한 배열 / ArrayList를 수정하는 경우, 그것들을 병렬로 유지하는 것은 매우 간단합니다. 동시에 추가 / 제거하는 한 배열의 크기가 변경되면 다시 빌드 할 필요가 없기 때문에 ArrayList의 경우 더 쉽습니다.