2015-11-04 62 views
2

在Kotlin中,Map類有toLinkedMap()toSortedMap()擴展方法。Kotlin Map:爲什麼沒有toHashMap()?

但爲什麼沒有toHashMap()方法?實際上,由此產生的Map許多stdlib方法的實現是LinkedHashMap,但在我的代碼中將其轉換爲HashMap會使我依賴於不好的實現。

引入這樣的方法會使開發人員無法深入到實現中,而使用當前實現它只會執行強制轉換。

我的使用情況是:

val matchesInClass: HashMap<MessageClass, HashMap<Int, Int>> 

//... 

for ((cl, matches) in matchesInClass) { 
    matchesInClass[cl] = matches.filterKeys { it !in banned } //error: not a HashMap 
} 

當我使用HashMap(matches.filterKeys { it !in banned })它會導致創建一個新的地圖,我很樂意避免的開銷。

那麼,它是由設計?

+1

爲什麼你需要matchesInClass的第二個類型參數是HashMap中,而不是簡單的地圖或MutableMap? 即matchInClass的類型爲'HashMap >' – Ilya

+0

@Ilya,'Map'不會因爲'// ...'部分我執行'matchesInClass'值的編輯。 'MutableMap'不適合:'filterKeys'返回無法轉換爲'MutableMap'的'Map'。 – hotkey

+0

問題是「爲什麼」或「意見」可能被標記爲關閉,因爲他們並不真正要求解決問題。你應該編輯你的問題,詢問創建'toHashMap'函數的最佳方式,或者你給定問題的替代方法(例如filterKeys不返回你想要的)。其他地方最好問產品功能的狀態,設計決定和開放式問題。 –

回答

1

我同意這個地方在stdlib是不方便的。但你想如何實現這樣一個功能toHashMap()

如果底層映射是HashMap,則最簡單的實現會進行轉換as HashMap,否則將其轉換。因此,在更改實現的情況下,該代碼的性能將發生顯着變化。那很糟。

所以,恕我直言,我更喜歡不安全的演員,如果stdlib以一種奇怪的方式改變並失敗,並提醒我。

總之,歡迎您將此問題報告爲YouTrack http://youtrack.jetbrains.com/issues/KT中的一張票。你在這裏對問題做了一個很好的描述,所以不需要很長時間。

0

如何只過濾這樣的:

val filtered = matchesInClass.mapValues { it.value.filterKeys { it !in banned } }

2

爲什麼?很難回答,但搜索或添加門票Kotlin issue tracker將爲您提供答案,並在狀態更改時更新您的答案。它看起來似乎toHashMap丟失,因爲toHashSet在那裏(as-of 1.0 BETA 4)。

注:是LinkedHashMap的是默認的,因爲科特林希望當你從ListSetListMapList並確保事情仍處於相對爲了維護元素的順序。

無論如何,在此期間,這裏是一個自定義toHashMap你:

public fun <K, V> Iterable<Pair<K, V>>.toHashMap(): Map<K, V> 
    = HashMap<K, V>(collectionSizeOrNull() ?: 16).apply { putAll([email protected]) } 

你可以把它更好地使用類似於toMap功能挑選最好的初始地圖大小的邏輯,還是不要設置它並相信默認增長實施。

Kotlin的構建很容易擴展。如果所有東西都放在stdlib中,那麼受限制的設備(如Android)上的用戶會抱怨它太大了,而且大多數人所要求的東西都是小怪物,它們是放入自定義lib中的幾行代碼。

1

這不是您原始問題的答案,而是您的使用案例的替代解決方案。

在這裏,我們試圖篩選HashMap<Int, Int>並將其分配回到地圖這是摘自:

matchesInClass[cl] = matches.filterKeys { it !in banned } //error: not a HashMap

如果你沒有要求保持matches HashMap的完整,你可以就地通過篩選它其keys可變集調用removeAll功能:

val matchesInClass: HashMap<MessageClass, HashMap<Int, Int>> 

//... 

for (matches in matchesInClass.values) { 
    matches.keys.removeAll { it in banned } // notice the inverted condition 
} 

這將是比創建一個過濾副本更有效。

另一種方法是使用提供所需的類型的空地圖Map.filterTo

for (entry in matchesInClass) { 
    entry.setValue(entry.value.filterTo(HashMap()) { it !in banned }) 
} 
相關問題