我創建了以下方法,將給定的 UUID 值與給定的整數添加到map變數中。
final Map<Integer, List<UUID>> map = new TreeMap<>();
private void addToMap(Integer key, UUID value) {
map.computeIfAbsent(key, val -> new ArrayList<>()).add(value);
}
通常我試圖map.computeIfAbsent(key, value -> new ArrayList<>()).add(value);通過將value引數傳遞給 lambda 函式來使用它,它會拋出“變數‘值’已經在范圍中定義”錯誤指向.. value -> ...部分“值” 。
我更新的addToMap方法有效,但我認為val毫無意義。那么,這個方法應該如何更新呢?
uj5u.com熱心網友回復:
根據JLS 15.27.2,lambda 運算式不會從封閉范圍內隱藏變數。Lambda 與 Java 中的其他塊非常相似。
JLS 6.4提供了有關該主題的一些指導。
有兩種設計備選方案可用于處理由 lambda 引數和 lambda 運算式中宣告的其他變數創建的名稱沖突。一種是模仿類宣告:與本地類一樣,lambda 運算式為名稱引入了一個新的“級別”,并且運算式之外的所有變數名稱都可以重新宣告。另一種是“本地”策略:與 catch 子句、for 回圈和塊一樣,lambda 運算式在與封閉背景關系相同的“級別”上運行,并且運算式之外的區域變數不能被遮蔽。以上規則使用本地策略;沒有特殊的特權允許在 lambda 運算式中宣告的變數隱藏在封閉方法中宣告的變數。
強調我的。
但是,鑒于您的代碼,如果引數名稱困擾您,您應該能夠擺脫它。請注意,引數只是傳遞給ArrayList建構式。您將建構式包裝在 lambda 運算式中,該運算式用作computeIfAbsent所需的映射函式的行內實作。
您正在創建一個函式,該函式接受一個值并將其包裝在一個串列中。請注意,建構式本身就是這樣一個函式,因此computeIfAbsent直接將建構式參考作為引數傳遞給它就足夠了。
private void addToMap(Integer key, UUID value) {
map.computeIfAbsent(key, ArrayList::new).add(value);
}
它是否更具可讀性是有爭議的。就個人而言,我喜歡這里的方式val和value不能混淆。很明顯,建構式是這里的引數,而不是它稍后將使用的值。
uj5u.com熱心網友回復:
您的addToMap()方法意味著對computeIfAbsent()方法引數的錯誤理解:
private void addToMap(Integer key, UUID value) {
map.computeIfAbsent(key, val -> new ArrayList<>()).add(value);
}
引數 inval -> new ArrayList<>()與value您傳入的引數無關addToMap()!
如果您查看Map.computeIfAbsent()的 JavaDoc,您可以看到第二個引數是 a Function<? super K,?? extends V>- 即一個函式,它接受一個鍵并回傳應該存盤在地圖中的任何內容。
最好將addToMap()方法寫為
private void addToMap(Integer key, UUID value) {
map.computeIfAbsent(key, k -> new ArrayList<>()).add(value);
}
請注意,toniedzwiedz 的回答是危險的。它僅適用于Map<Integer, ?>鍵大于或等于零的 a。
這是危險的,因為它基本上取代k -> new ArrayList<>()了k -> new ArrayList<>(k)- 這恰好適用于帶有Integer鍵的映射并使用鍵值來定義ArrayList.
如果k為負則不起作用(如果 k 為負,new ArrayList<>(k)則會拋出一個IllegalArgumentException)。
它也不適用于 aMap<String, UUID>因為沒有ArrayList帶String引數的構造函式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/313180.html
