val selectedSeries = series.toList()działa również, ponieważ wzywa toMutableList()do jego wykonania.
Flávio Faria
4
@ FlávioFaria właśnie go przetestował ===i muszę powiedzieć, toList()że nie kopiuje kolekcji, ale toMutableList()robi
Peppermint Paddy
3
@PeppermintPaddy To robi kopię, z wyjątkiem przypadku pustych list. Jeśli źródło jest puste, Iterable.toList()zwraca emptyList(), która zawsze zwraca ten sam (niezmienny) obiekt. Więc jeśli przeprowadzisz test emptyList(), otrzymasz z powrotem ten sam obiekt.
Laurence Gonsalves
52
Osobiście nie podoba mi się ten pomysł ... Nic w dotacji nie toMutableList()powinno zwracać nowej instancji listy, jeśli instancja wywołująca metodę jest już listą modyfikowalną.
BrunoJCM
4
to nie jest dobra odpowiedź, a na pewno nie właściwa, nie ma gwarancji, że przyszłe implementacje mogą się zmienić, chyba że wyraźnie udokumentowano, że to wywołanie metody zawsze zwróci nową kopię.
Bhargav,
23
Możesz użyć
Lista -> toList ()
Array -> toArray ()
ArrayList -> toArray ()
MutableList -> toMutableList ()
Przykład:
val array = arrayListOf("1","2","3","4")val arrayCopy = array.toArray()// copy array to other arrayLog.i("---> array ", array?.count().toString())Log.i("---> arrayCopy ", arrayCopy?.count().toString())
array.removeAt(0)// remove first item in array Log.i("---> array after remove", array?.count().toString())Log.i("---> arrayCopy after remove", arrayCopy?.count().toString())
drukuj dziennik:
array:4
arrayCopy:4
array after remove:3
arrayCopy after remove:4
Aktualizacja: dzięki nowemu silnikowi wnioskowania o typie (opt-in w Kotlin 1.3) możemy pominąć ogólny parametr typu w pierwszym przykładzie i mieć to:
FYI. Sposobem na włączenie nowego wnioskowania jest użycie kotlinc -Xnew-inference ./SourceCode.ktwiersza poleceń lub kotlin { experimental { newInference 'enable'}Gradle. Aby uzyskać więcej informacji na temat nowego wnioskowania o typie, obejrzyj ten film: KotlinConf 2018 - Nowe wnioskowanie o typie i powiązane funkcje językowe autorstwa Svetlany Isakovej , zwłaszcza `` wnioskowanie dla budowniczych '' w wieku 30 lat
należy podzielić na 2 odpowiedzi imho, ponieważ uważam, że pierwsza jest poprawna, ale drugiej brakuje trochę urody.
Holger Brandl
@Jacob Wu: Byłem zaskoczony, widząc, że symbol * w drugim rozwiązaniu nie spowodował błędu. Co to robi? Wyszukałem z „mnożeniem jednoargumentowym”, ale nic nie znalazłem.
Lensflare
1
@Lensflare * oznacza zniszczenie tablicy na oddzielne elementy, np. MutableListOf (* [1, 2, 3]) oznacza mutableListOf (1, 2, 3), to jest jak operacja odwrotna do vararg
Jacob Wu
1
@Jacob Wu: Dziękuję. Dzięki Twojej odpowiedzi dowiedziałem się, że operator nazywa się „operatorem rozproszenia”. Widzę, jak to pomaga, łącząc niektóre parametry z tablicą w listę varargs. Ale jakie korzyści daje to w twoim przykładzie? Szybciej czy coś? A może jest to klucz do skopiowania kolekcji?
Lensflare
@Lensflare Myślę, że korzyścią jest tylko składnia - kod jest krótki i nie jest wymagany żaden wyraźny typ ogólny (jak w moim pierwszym przykładzie). Za kulisami uważam, że kod jest kompilowany do operacji tablicowych, więc wydajność powinna być taka sama.
Możesz skorzystać z podanego rozszerzenia, Iterable.toMutableList()które zapewni Ci nową listę. Niestety, jak sugeruje jego podpis i dokumentacja , ma to na celu zapewnienie, że an Iterablejest List(podobnie jak toStringi wiele innych to<type>metod). Nic nie gwarantuje, że będzie to nowa lista. Na przykład dodanie następującego wiersza na początku rozszerzenia: if (this is List) return thisjest uzasadnioną poprawą wydajności (jeśli rzeczywiście poprawia wydajność).
Ponadto ze względu na nazwę otrzymany kod nie jest zbyt jasny.
Wolę dodać własne rozszerzenie, aby mieć pewność wyniku i stworzyć znacznie bardziej przejrzysty kod (tak jak w przypadku tablic ):
fun<T>List<T>.copyOf():List<T>{val original =thisreturn mutableListOf<T>().apply { addAll(original)}}fun<T>List<T>.mutableCopyOf():MutableList<T>{val original =thisreturn mutableListOf<T>().apply { addAll(original)}}
Zauważ, że addAlljest to najszybszy sposób kopiowania, ponieważ używa natywnego System.arraycopyw implementacji ArrayList.
Podoba mi się to rozwiązanie. Czy nie powinno addAll(this@copyOf), bo thiswewnątrz applybędzie odnosić się do nowo utworzonej pustej listy? Albo to, albo mutableListOf<T>().also { it.addAll(this) }?
Zauważ, że to nie działa dla Maps. Kompiluje się, ale ponieważ itjest a Map.Entry, a kopia jest płytka, masz te same wpisy.
noamtm
1
@noamtm tak, to właśnie mam na myśli w przypadku płytkiej kopii. Ta metoda nigdy nie skopiuje wpisów. Utworzy tylko kopię kolekcji z tymi samymi wpisami. Mapa nie jest tutaj niczym specjalnym.
Lensflare
2
Chodzi mi o to, że chociaż kuszące jest używanie go również na mapach, a kompiluje się i wydaje się działać - tak naprawdę nie działa.
noamtm
4
Podobnie jak w Javie:
Lista:
val list = mutableListOf("a","b","c")val list2=ArrayList(list)
Mapa:
val map = mutableMapOf("a" to 1,"b" to 2,"c" to 3)val map2=HashMap(map)
Zakładając, że celujesz w JVM (lub Android); Nie jestem pewien, czy działa dla innych celów, ponieważ opiera się na konstruktorach kopiujących ArrayList i HashMap.
val original = listOf("A","B","C")val copy = original.toCollection(mutableListOf())
Spowoduje to utworzenie nowego, MutableLista następnie dodanie każdego elementu oryginału do nowo utworzonej listy.
Wywnioskowanym typem będzie tutaj MutableList<String>. Jeśli nie chcesz ujawniać zmienności tej nowej listy, możesz jawnie zadeklarować typ jako niezmienną listę:
val copy:List<String>= original.toCollection(mutableListOf())
Dla prostych list ma wiele poprawnych rozwiązań powyżej.
Jednak jest to tylko dla płytkich list.
Poniższa funkcja działa dla wszystkich dwuwymiarowych ArrayList. ArrayListjest w praktyce odpowiednikiem MutableList. Co ciekawe, nie działa przy użyciu MutableListtypu jawnego . Jeśli potrzeba więcej wymiarów, konieczne jest wykonanie większej liczby funkcji.
fun<T>cloneMatrix(v:ArrayList<ArrayList<T>>):ArrayList<ArrayList<T>>{varMatrResult=ArrayList<ArrayList<T>>()for(i in v.indices)MatrResult.add(v[i].clone()asArrayList<T>)returnMatrResult}
Demo dla Matrix liczb całkowitych:
var mat = arrayListOf(arrayListOf<Int>(1,2),arrayListOf<Int>(3,12))var mat2=ArrayList<ArrayList<Int>>()
mat2= cloneMatrix<Int>(mat)
mat2[1][1]=5
println(mat[1][1])
Odpowiedzi:
To działa dobrze.
źródło
val selectedSeries = series.toList()
działa również, ponieważ wzywatoMutableList()
do jego wykonania.===
i muszę powiedzieć,toList()
że nie kopiuje kolekcji, aletoMutableList()
robiIterable.toList()
zwracaemptyList()
, która zawsze zwraca ten sam (niezmienny) obiekt. Więc jeśli przeprowadzisz testemptyList()
, otrzymasz z powrotem ten sam obiekt.toMutableList()
powinno zwracać nowej instancji listy, jeśli instancja wywołująca metodę jest już listą modyfikowalną.Możesz użyć
Lista -> toList ()
Array -> toArray ()
ArrayList -> toArray ()
MutableList -> toMutableList ()
Przykład:
drukuj dziennik:
źródło
Mogę wymyślić dwa alternatywne sposoby:
Aktualizacja: dzięki nowemu silnikowi wnioskowania o typie (opt-in w Kotlin 1.3) możemy pominąć ogólny parametr typu w pierwszym przykładzie i mieć to:
FYI. Sposobem na włączenie nowego wnioskowania jest użycie
kotlinc -Xnew-inference ./SourceCode.kt
wiersza poleceń lubkotlin { experimental { newInference 'enable'}
Gradle. Aby uzyskać więcej informacji na temat nowego wnioskowania o typie, obejrzyj ten film: KotlinConf 2018 - Nowe wnioskowanie o typie i powiązane funkcje językowe autorstwa Svetlany Isakovej , zwłaszcza `` wnioskowanie dla budowniczych '' w wieku 30 latźródło
Jeśli twoja lista zawiera klasę danych kotlin , możesz to zrobić
źródło
Możesz skorzystać z podanego rozszerzenia,
Iterable.toMutableList()
które zapewni Ci nową listę. Niestety, jak sugeruje jego podpis i dokumentacja , ma to na celu zapewnienie, że anIterable
jestList
(podobnie jaktoString
i wiele innychto<type>
metod). Nic nie gwarantuje, że będzie to nowa lista. Na przykład dodanie następującego wiersza na początku rozszerzenia:if (this is List) return this
jest uzasadnioną poprawą wydajności (jeśli rzeczywiście poprawia wydajność).Ponadto ze względu na nazwę otrzymany kod nie jest zbyt jasny.
Wolę dodać własne rozszerzenie, aby mieć pewność wyniku i stworzyć znacznie bardziej przejrzysty kod (tak jak w przypadku tablic ):
Zauważ, że
addAll
jest to najszybszy sposób kopiowania, ponieważ używa natywnegoSystem.arraycopy
w implementacjiArrayList
.Uważaj również, że da ci to tylko płytką kopię .
źródło
addAll(this@copyOf)
, bothis
wewnątrzapply
będzie odnosić się do nowo utworzonej pustej listy? Albo to, albomutableListOf<T>().also { it.addAll(this) }
?Sugeruję, aby uzyskać płytką kopię
To zadziała w przypadku wielu typów kolekcji.
źródło
Map
s. Kompiluje się, ale ponieważit
jest aMap.Entry
, a kopia jest płytka, masz te same wpisy.Podobnie jak w Javie:
Lista:
Mapa:
Zakładając, że celujesz w JVM (lub Android); Nie jestem pewien, czy działa dla innych celów, ponieważ opiera się na konstruktorach kopiujących ArrayList i HashMap.
źródło
Chciałbym skorzystać z
toCollection()
metody rozszerzenie :Spowoduje to utworzenie nowego,
MutableList
a następnie dodanie każdego elementu oryginału do nowo utworzonej listy.Wywnioskowanym typem będzie tutaj
MutableList<String>
. Jeśli nie chcesz ujawniać zmienności tej nowej listy, możesz jawnie zadeklarować typ jako niezmienną listę:źródło
Dla prostych list ma wiele poprawnych rozwiązań powyżej.
Jednak jest to tylko dla płytkich list.
Poniższa funkcja działa dla wszystkich dwuwymiarowych
ArrayList
.ArrayList
jest w praktyce odpowiednikiemMutableList
. Co ciekawe, nie działa przy użyciuMutableList
typu jawnego . Jeśli potrzeba więcej wymiarów, konieczne jest wykonanie większej liczby funkcji.Demo dla Matrix liczb całkowitych:
to pokazuje
12
źródło
Możesz użyć
ArrayList
konstruktora:ArrayList(list)
źródło
Wypróbuj poniższy kod do kopiowania listy w Kotlinie
źródło