Kotlin에서 목록을 복제하거나 복사하는 방법


102

Kotlin에서 목록을 복사하는 방법은 무엇입니까?

나는 사용하고있다

val selectedSeries = mutableListOf<String>()
selectedSeries.addAll(series)

더 쉬운 방법이 있습니까?


1
딥 클로닝이 필요하지 않은 경우 솔루션이 이미 가장 쉬운 방법이라고 생각합니다.
Serdar Samancıoğlu

답변:


145

이것은 잘 작동합니다.

val selectedSeries = series.toMutableList()

6
val selectedSeries = series.toList()또한 toMutableList()구현을 호출하기 때문에 작동합니다 .
Flávio Faria

4
FlávioFaria @ 단지 그것을 테스트 ===하고 말할 필요가 toList()컬렉션을 복사하지 않습니다,하지만 toMutableList()않습니다
박하 패디을

3
@PeppermintPaddy 그것은 않습니다 빈 목록의 경우를 제외하고, 사본을. 소스가 비어있는 경우 Iterable.toList()반환 emptyList()항상 같은 (불변) 객체를 반환한다. 따라서 테스트 emptyList()하면 동일한 개체를 다시 얻을 수 있습니다.
Laurence Gonsalves 2018

52
개인적으로이 아이디어가 마음에 들지 않습니다 toMutableList(). 메서드를 호출하는 인스턴스가 이미 변경 가능한 목록 인 경우 목록의 새 인스턴스를 반환해야하는 문서 부여 내용은 없습니다 .
BrunoJCM

4
이것은 좋은 대답이 아니며 확실히 올바른 대답도 아닙니다.이 메서드 호출이 항상 새 복사본을 반환한다고 구체적으로 문서화하지 않는 한 향후 구현이 변경 될 수 있다는 보장은 없습니다.
Bhargav

23

당신이 사용할 수있는

목록-> toList ()

배열-> toArray ()

ArrayList-> toArray ()

MutableList-> toMutableList ()


예:

val array = arrayListOf("1", "2", "3", "4")

val arrayCopy = array.toArray() // copy array to other array

Log.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())

인쇄 로그 :

array: 4
arrayCopy: 4
array after remove: 3
arrayCopy after remove: 4

14

두 가지 대안을 생각해 낼 수 있습니다.

1. val selectedSeries = mutableListOf<String>().apply { addAll(series) }

2. val selectedSeries = mutableListOf(*series.toTypedArray())

업데이트 : 새로운 유형 추론 엔진 (Kotlin 1.3에서 옵트 인)을 사용하여 첫 번째 예제에서 일반 유형 매개 변수를 생략하고 다음을 가질 수 있습니다.

1. val selectedSeries = mutableListOf().apply { addAll(series) }

참고로 새 추론을 옵트 인하는 방법은 kotlinc -Xnew-inference ./SourceCode.kt명령 줄 또는 kotlin { experimental { newInference 'enable'}Gradle입니다. 새로운 유형 추론에 대한 자세한 내용은 KotlinConf 2018-Svetlana Isakova의 새로운 유형 추론 및 관련 언어 기능 , 특히 '빌더를위한 추론 '30 ' 동영상을 확인하세요.


첫 번째가 맞다고 생각하기 때문에 2 개의 답변으로 나눠야합니다. 그러나 후자는 약간의 아름다움이 부족합니다.
Holger Brandl

@Jacob Wu : 두 번째 솔루션의 * 기호가 오류를 생성하지 않는 것을보고 놀랐습니다. 그것은 무엇을합니까? "단항 곱셈"으로 검색했지만 아무것도 찾지 못했습니다.
Lensflare

1
@Lensflare *는 배열을 별도의 항목으로 소멸하는 것을 의미합니다. 예를 들어 mutableListOf (* [1, 2, 3])는 mutableListOf (1, 2, 3)을 의미합니다. 이는 vararg의 반대 연산과 같습니다
Jacob Wu

1
@Jacob Wu : 감사합니다. 귀하의 답변으로 운영자가 "스프레드 운영자"라는 것을 알 수있었습니다. 일부 매개 변수를 배열과 결합하여 varargs 목록으로 만드는 것이 어떻게 도움이되는지 확인합니다. 그러나 귀하의 예에서 어떤 이점이 있습니까? 더 빠르거나 뭔가? 아니면 컬렉션이 복사되었는지 확인하는 것이 중요합니까?
Lensflare

@Lensflare 장점은 구문 일 뿐이라고 생각합니다. 코드가 짧고 명시적인 제네릭 유형이 필요하지 않습니다 (첫 번째 예제와 같이). 배후에서는 코드가 배열 연산으로 컴파일되었다고 생각하므로 성능은 동일해야합니다.
Jacob Wu


9

Iterable.toMutableList()새 목록을 제공 하는 제공된 확장 을 사용할 수 있습니다 . 의 서명과 불행하게도, 문서 제안,는이 수 있도록 의미있어 IterableA는 List(처럼 toString많은 다른 to<type>방법). 새로운 목록 이 될 것이라는 보장은 없습니다 . 예를 들어 확장 시작 부분에 다음 줄을 추가하면 if (this is List) return this합법적 인 성능 향상입니다 (실제로 성능이 향상되는 경우).

또한 이름 때문에 결과 코드가 명확하지 않습니다.

나는 결과를 확인하고 훨씬 더 명확한 코드를 만들기 위해 내 자신의 확장을 추가하는 것을 선호합니다 ( 배열의 경우처럼 ).

fun <T> List<T>.copyOf(): List<T> {
    val original = this
    return mutableListOf<T>().apply { addAll(original) }
}

fun <T> List<T>.mutableCopyOf(): MutableList<T> {
    val original = this
    return mutableListOf<T>().apply { addAll(original) }
}

참고 addAll는 기본 사용하기 때문에 복사 할 수있는 가장 빠른 방법 System.arraycopy의 구현을 ArrayList.

또한 이것은 당신에게 얕은 사본 만 제공한다는 점에 유의하십시오 .


이 솔루션이 마음에 듭니다. 내부 가 새로 생성 된 빈 목록을 참조하기 addAll(this@copyOf)때문에 이어야하지 않습니까? 아니면 ? thisapplymutableListOf<T>().also { it.addAll(this) }
Franko Leon Tokalić

5

얕은 카피의 경우

.map{it}

이는 많은 컬렉션 유형에서 작동합니다.


1
Maps 에서는 작동하지 않습니다 . 컴파일되지만 itMap.Entry이고 사본이 얕기 때문에 동일한 항목이 있습니다.
noamtm

1
@noamtm 예, 그것이 얕은 카피의 의미입니다. 이 방법은 항목을 복사하지 않습니다. 동일한 항목이있는 컬렉션의 복사본 만 만듭니다. 여기서지도는 특별한 것이 아닙니다.
Lensflare

2
내 요점은 맵에서도 사용하고 싶은 유혹이 있고 컴파일되고 작동하는 것처럼 보이지만 실제로 작동하지 않는다는 것입니다.
noamtm

4

Java에서와 같이 :

명부:

    val list = mutableListOf("a", "b", "c")
    val list2 = ArrayList(list)

지도:

    val map = mutableMapOf("a" to 1, "b" to 2, "c" to 3)
    val map2 = HashMap(map)

JVM (또는 Android)을 대상으로한다고 가정합니다. ArrayList 및 HashMap의 복사 생성자에 의존하기 때문에 다른 대상에서 작동하는지 확실하지 않습니다.


2

확장 방법을 사용 합니다toCollection() .

val original = listOf("A", "B", "C")
val copy = original.toCollection(mutableListOf())

그러면 새로 생성 된 MutableList다음 원본의 각 요소가 새로 생성 된 목록에 추가됩니다.

여기서 추론 된 유형은입니다 MutableList<String>. 이 새 목록의 변경 가능성을 노출하지 않으려면 유형을 변경 불가능한 목록으로 명시 적으로 선언 할 수 있습니다.

val copy: List<String> = original.toCollection(mutableListOf())

0

간단한 목록의 경우 위에 올바른 솔루션이 많이 있습니다.

그러나 그것은 단지 얕은 목록을위한 것입니다.

아래 함수는 모든 2 차원에서 작동합니다 ArrayList. ArrayList실제로는 MutableList. 흥미롭게도 명시 적 MutableList유형을 사용할 때는 작동하지 않습니다 . 더 많은 차원이 필요하면 더 많은 기능을 만들어야합니다.

fun <T>cloneMatrix(v:ArrayList<ArrayList<T>>):ArrayList<ArrayList<T>>{
  var MatrResult = ArrayList<ArrayList<T>>()
  for (i in v.indices) MatrResult.add(v[i].clone() as ArrayList<T>)
  return MatrResult
}

정수 행렬 데모 :

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])

이것은 보여준다 12



-1

Kotlin 에서 목록을 복사하려면 아래 코드를 시도하십시오.

arrayList2.addAll(arrayList1.filterNotNull())
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.