我有一個對象列表。對象被賦予一個ID並存儲在一個Hashtable中。如果我需要有特定ID的對象,我只是說:Java中的雙向集合
ht.get(ID);
不過,有時我需要的ID給定對象:
ht.get(Object);
我最初的想法是使用兩個不同的哈希表;一個用於ID - >對象映射,另一個用於對象 - > ID映射。
這聽起來像是一個足夠好的解決方案嗎?
我有一個對象列表。對象被賦予一個ID並存儲在一個Hashtable中。如果我需要有特定ID的對象,我只是說:Java中的雙向集合
ht.get(ID);
不過,有時我需要的ID給定對象:
ht.get(Object);
我最初的想法是使用兩個不同的哈希表;一個用於ID - >對象映射,另一個用於對象 - > ID映射。
這聽起來像是一個足夠好的解決方案嗎?
如果你不能使用外部集合(因爲你似乎不想使用給定的一個評論),你可以寫一個簡單的類來做你想做的事(這是的,實質上是你的第一個想法),沿着(我沒有編譯這個,這只是第一個想法,所以可能是一個壞主意,等等......):
編輯:現在有兩個版本,一個允許重複值和一個那不。如果值被覆蓋,那些不會刪除密鑰的。
這個版本不允許重複的值:
class Foo<K, V>
{
private final Map<K, V> keyValue;
private final Map<V, K> valueKey;
{
keyValue = new HashMap<K, V>();
valueKey = new HashMap<V, K>();
}
// this makes sure that if you do not have duplicate values.
public void put(final K key, final V value)
{
if(keyValue.containsValue(value))
{
keyValue.remove(valueKey.get(value));
}
keyValue.put(key, value);
valueKey.put(value, key);
}
public V getValueForKey(final K key)
{
return (keyValue.get(key));
}
public K getKeyForValue(final V value)
{
return (valueKey.get(value));
}
public static void main(final String[] argv)
{
Foo<String, String> foo;
foo = new Foo<String, String>();
foo.put("a", "Hello");
foo.put("b", "World");
foo.put("c", "Hello");
System.out.println(foo.getValueForKey("a"));
System.out.println(foo.getValueForKey("b"));
System.out.println(foo.getValueForKey("c"));
System.out.println(foo.getKeyForValue("Hello"));
System.out.println(foo.getKeyForValue("World"));
}
}
該版本允許重複值,給你回所有具有給定值的所有鍵的列表:
class Foo<K, V>
{
private final Map<K, V> keyValue;
private final Map<V, List<K>> valueKeys;
{
keyValue = new HashMap<K, V>();
valueKeys = new HashMap<V, List<K>>();
}
public void put(final K key, final V value)
{
List<K> values;
keyValue.put(key, value);
values = valueKeys.get(value);
if(values == null)
{
values = new ArrayList<K>();
valueKeys.put(value, values);
}
values.add(key);
}
public V getValueForKey(final K key)
{
return (keyValue.get(key));
}
public List<K> getKeyForValue(final V value)
{
return (valueKeys.get(value));
}
public static void main(final String[] argv)
{
Foo<String, String> foo;
foo = new Foo<String, String>();
foo.put("a", "Hello");
foo.put("b", "World");
foo.put("c", "Hello");
System.out.println(foo.getValueForKey("a"));
System.out.println(foo.getValueForKey("b"));
System.out.println(foo.getValueForKey("c"));
System.out.println(foo.getKeyForValue("Hello"));
System.out.println(foo.getKeyForValue("World"));
}
}
隱藏在一個類中的兩個地圖是一個好主意,因爲你後來發現了一個更好的方法,所有你需要做的就是替換這個類的內部,而你的代碼的其餘部分保持不變。
完美的答案。對於Java新手來說,注意集合不僅僅是索引 - 它們不重複信息,只包含對它的引用。這意味着此解決方案不會複製包含的任何信息,它只包含兩個散列索引,這是此問題的最佳解決方案。 – 2010-07-07 23:20:04
這不能正常工作。您應該注意,相同的值不會插入到地圖中。考慮 myFoo.put(「a」,「foo」); myFoo.put(「b」,「foo」); – 2010-07-08 18:36:09
我確實考慮過這一點,但忘記了它會使其中一個地圖與另一個地圖不一致。我通過兩種方式修復了它(我相信),其中一個刪除無效密鑰,另一個使用列表維護重複項。 – TofuBeer 2010-07-08 18:59:35
如果使用外部庫是OK,你應該檢查在谷歌收藏BIMAP: http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/BiMap.html
不使用外部庫..我註定了嗎? – user318247 2010-07-07 22:57:24
您可以隨時自行實施。最常見的方法是使用2個哈希表並保持同步。您可以在google-collections中查看AbstractBiMap的來源。 – bashflyng 2010-07-07 23:04:57
你所尋找的是一個雙向映射。您可以在執行BidiMap接口或Google Guava的類中的commons collections中找到它。
你在找什麼是一個雙向地圖。 嘗試Apache集合BidiMap。
http://commons.apache.org/collections/api-3.1/org/apache/commons/collections/BidiMap.html
哦,被打了2秒。 :-) – 2010-07-07 22:58:17
不,我知道immediatley的,但你可以建立一個...如何讓你的對象和幾個查找結構(包含HashMap或樹)不存儲對象本身的一個集合(爲了記憶保存的原因),但索引到你的單一集合?通過這種方式,您可以使用您需要的適當的查找結構(Id - >對象或反之亦然)獲取可以索引到原始集合中的整數值。這樣,您可以做的不僅僅是雙向查找,以防將來需要這樣做。
這隻有在HashTables相當靜態時纔有用。如果你有很多更新的表,這個方法需要更新兩個HashTables – 2010-07-07 22:56:30
通常(通常是?)ID是對象本身的一部分,所以後者變成'object.getId()'。或者在你的情況下不適合? – doublep 2010-07-07 22:58:57
他們經常更新!兩張桌子似乎對我來說是骯髒的解決方案...但是..好吧.. – user318247 2010-07-07 23:01:41