2016-07-26 10 views

Odpowiedz

6

Następująca funkcja rozszerzenia działa, kopiując Map do MutableMap.

fun <K, V> Map<K, V>.toMutableMap(): MutableMap<K, V> { 
    return HashMap(this) 
} 
9

Po pierwsze, jak ujęte w poprzednich pytań o Kotlin tylko do odczytu zbiorów i ich niezmienność, są one naprawdę tylko do odczytu żyć widoki prawdopodobnych modyfikowalnych kolekcjach.

Kotlin może bezpiecznie sprawdzić typ dla zmienności dla nich, ponieważ istnieją markery na interfejsy, które umożliwiają Kotlin wiedzieć, na przykład:

// assuming some variable readOnlyMap of type Map<String, String> 

val mutableMap: MutableMap<String, String> = if (readOnlyMap is MutableMap<*,*>) { 
    readOnlyMap as MutableMap 
} else { 
    HashMap(readOnlyMap) 
} 

Kontrola ta is wewnętrznie wywołuje TypeIntrinsics.isMutableMap i jest poprawnym sposobem wiedzieć, czy można je odlewać. Nie ma niebezpieczeństwa w obsadzie, jeśli najpierw wykonasz tę kontrolę. Zauważysz, że kompilator jest całkowicie zadowolony i bez ostrzeżeń. Może to być niebezpieczne, jeśli nie zamierzasz modyfikować tej samej mapy traktowanej jako tylko do odczytu, ale pokazuje ona, że ​​możesz rzucić o afekt.

Jeśli nie chcesz modyfikować oryginalnej mapy, oczywiście zawsze rób kopię, po prostu wywołując konstruktora HashMap z inną mapą, HashMap(readOnlyMap). Lub złożyć funkcję przedłużacza:

fun <K, V> Map<K, V>.toMutableCopy() = HashMap(this) 

i nazywają go:

val mutableMap = readOnlyMap.toMutableCopy() 

A teraz masz prostą drogę.

Zobacz także:

+0

Myślę, że powinieneś wyraźnie określić rodzajowe elementy HashMap, w przeciwnym razie otrzymasz mapę z typami klucz/wartość platformy. –

+2

Odradzam sprawdzanie 'is MutableMap', ponieważ może zwrócić' true' dla kolekcji Java, które nie są w rzeczywistości zmienne. Na przykład spróbuj 'Collections.unmodifiableMap (mutableMapOf (" a "do" b ")) to MutableMap <*,*>'. –

+0

To wygląda na najlepszą odpowiedź. Jedną z rzeczy, które możesz dodać, jest przykład, który nie używa bezpośrednio 'HashMap' (uważam, że' mutableMapOf' faktycznie używa 'LinkedHashMap'). np .: 'val mutableMap = map.entries.associateTo (mutableMapOf()) {entry -> entry.toPair()}'. – mfulton26