2012-11-23 61 views
5

我有一個包含多個鍵值列表的類。每個鍵(在一個列表中)應該是唯一的,所以我使用HashMap。當代碼中的某處添加一個新項目時,我使用HashMap的put(K, V)。如果嘗試添加已有鍵的項目,我希望我的代碼拋出異常。而且,因爲這樣的添加是在程序中的許多地方執行的,所以我想避免在每個地方添加檢查。所以它應該是列表類本身,不允許替換現有的鍵值對。帶唯一性檢查的HashMap

我想到用我自己的擴展HashMap類,它會執行這樣的檢查並拋出異常。但是,HashMap的put不會拋出異常,所以我也做不到。

什麼是實現此類行爲的好方法?我準備好用更好的東西替換HashMap,但我需要它在添加和檢索項目中都很快。

更新: 感謝所有的許多不錯的建議。因爲我是一個Java的新手,所以我現在需要學習很多東西才能選擇最好的一個:)無論如何,我非常感謝在午餐時間內獲得如此多的選擇!

+0

Commons Collections沒有得到應有的曝光... – Isaac

回答

0

你可以拋出一個異常,該異常是extens RuntimeException。

+2

嘿你downvoter,我的回答是有效的。給出理由,你爲什麼downvote – AlexWien

+1

我不是downvoter,但我相信,downvoting的原因是,你提出了一個解決方案,將要求OP明確編碼自己的口供檢查,而OP明確表示,他們正在尋找一個可以自動完成的機制。 – Isaac

+1

@AlexWien我沒有倒下,但你會違反里斯科換人原則。 – Mik378

2

幾個想法:
A.拋出一個異常,它擴展了繼承HashMap的類中的RuntimeException。
B.提供某種MapWrapper,它將接收一個Map作爲參數,將有get,put和其他一些方法,以及更適合您的簽名。

+0

'B'已經存在。請參閱下面的答案。 – Isaac

+0

@zaske Liskov違反這裏也。 – Mik378

+0

@ Mik378,這裏的'A'違反LSP; 'B'不。但'B'已經在Commons Collections中可用(請參閱我的答案),不需要重新發明輪子。 – Isaac

7

您可以使用Commons Collections對於這一點,是這樣的:

Map map = MapUtils.predicatedMap(new HashMap(), PredicateUtils.uniquePredicate(), 
      null); 

這將創建一個Map例如當你嘗試插入鍵值對時相同的密鑰已經存在,將拋出異常。

當然,您可以通過構建自己的Predicate實例並使用它來代替PredicateUtils.uniquePredicate()來自定義此行爲。您自己的Predicate可以做任何您需要它做的事情,例如,它可以拋出與默認uniquePredicate()拋出的不同類型的異常。

6

我不會擴大HashMap類,因爲在這種情況下,因爲你改變基類方法的行爲,這將導致違反了里氏替換原則的。

相反,我會用組成:

創建CustomHashMap類實現Map接口,並具有HashMap場。 並重新聲明HashMap類中存在的每種方法,除put()方法外,每個方法都會向原始HashMap添加一個委派=>如果entry已存在,則拋出異常。

+0

+1提到LSP,並感謝您的解決方案。 – texnic

0

您可以擴展HashMap並拋出一個Exception,它是RuntimeException的子類或Put方法已拋出的Exception之一。

1

javadoc for Map#put states

拋出:IllegalArgumentException -如果指定鍵或值的某些屬性不允許將其存儲在此映射

我覺得你的使用情況屬於這一類別,因此,我會使用這種可能性。由於這是一個未經檢查的例外情況,因此您可以使用合成,包裝HashMap並在put方法中重複輸入IllegalArgumentException