스칼라에서 배열과리스트의 차이점


142

어떤 경우에는 Array (Buffer) 및 List (Buffer)를 사용해야합니다. 내가 아는 한 가지 차이점은 배열이 변하지 않고 목록이 공변량이라는 것입니다. 그러나 성능과 다른 특성은 어떻습니까?

답변:


155

불변의 구조

스칼라는 List당신이 (아마도)이보다 훨씬 더 그것을 사용되어야한다고 스칼라에서 이러한 기본 구조이다 불변의 재귀 데이터 구조입니다 Array(실제로있는 가변 - 불변 아날로그Array것입니다 IndexedSeq).

Java 배경에서 오는 경우 LinkedListover 를 사용 하는 것이 분명 ArrayList합니다. 전자는 일반적으로 순회 만 (및 크기가 사전에 알려지지 않은) 목록에 사용되는 반면 후자는 알려진 크기 (또는 최대 크기)가 있거나 빠른 임의 액세스 가 중요한 목록에 사용됩니다.

가변 구조

ListBuffer이후 변환이 필요한 경우 List에만 사용 ListBuffer하는 이유 인 상수 시간 변환을 제공 합니다.

스칼라 Array는 Java 배열에 의해 JVM에서 구현되어야하므로 새로운 기능 을 가진 최신 버전의 스칼라를 사용하지 않는 한 내용 보다 상자의 Array[Int]성능이 훨씬 뛰어 납니다. .int[]List[Int]@specialized

그러나 Array스칼라에서 s 의 사용은 최소한으로 유지되어야 한다고 생각합니다. 왜냐하면 배열에서 실제로 필요한 기본 유형에 의해 지원되는지 여부를 결정하기 위해 후드에서 무슨 일이 일어나고 있는지 알아야한다는 느낌이 들기 때문입니다. 랩퍼 유형으로 상자에 넣습니다.


또한 stackoverflow.com/questions/3213368/…stackoverflow.com/questions/2481149/… 를 참조하십시오. 어레이에 대한 "동일"의 정의는 동일한 어레이를 참조한다는 것입니다.
oluies

130

이미 게시 된 답변 외에도 몇 가지 세부 사항이 있습니다.

가 있지만 Array[A]Java 배열 그대로이고, A는 List[A]하나이며 불변의 데이터 구조 Nil(빈리스트) 또는 한 쌍의 구성은 (A, List[A]).

성능 차이

                          Array  List
Access the ith element    θ(1)   θ(i)
Delete the ith element    θ(n)   θ(i)
Insert an element at i    θ(n)   θ(i)
Reverse                   θ(n)   θ(n)
Concatenate (length m,n)  θ(n+m) θ(n)
Count the elements        θ(1)   θ(n)

메모리 차이

                          Array  List
Get the first i elements  θ(i)   θ(i)
Drop the first i elements θ(n-i) θ(1)
Insert an element at i    θ(n)   θ(i)
Reverse                   θ(n)   θ(n)
Concatenate (length m,n)  θ(n+m) θ(n)

따라서 빠른 임의 액세스가 필요하지 않거나 요소를 계산해야하거나 어떤 이유로 든 파괴적인 업데이트가 필요한 경우 List가 아니라 a 보다 낫습니다 Array.


이 Os는 목록을 복사 할 시간을 고려해야합니까? 나는 당신이 이와 같은 테스트를하고 있다고 가정합니다 : 예 : list = list.drop(i). 아니면 후드 뒤에 어떤 마법이 생깁니 까?

2
필요한 경우 복사 목록과 배열을 고려합니다. 일을 좋아합니다 drop떨어되지 않은 목록의 일부를 복사 할 필요가 없습니다. 예는 (x::xs).drop(1)정확히 xs이 아니 "복사" xs.
Apocalisp

6
이 무증상은 스칼라와 아무 관련이 없습니다. C의 동일한 데이터 구조는 일정한 요소까지 정확합니다.
Apocalisp

1
@Apocalisp이 정보를 참조했거나 어떤 조건 하에서 결정 했습니까?
Phil

1
@Phil 측정이 아닌 무증상입니다. 그들은 모든 조건에서 참될 것입니다.
Apocalisp

18

배열은 변경 가능합니다. 즉, 각 인덱스의 값을 변경할 수 있고 목록 (기본적으로)은 변경할 수 없습니다. 즉, 수정할 때마다 새 목록이 작성됩니다. 대부분의 경우 그것은 불변의 데이터 유형과 일에 대한보다 "기능"스타일이며, 당신은 아마 시도와 같은 구조를 가진 목록을 사용한다 yield, foreach, match등.

성능 특성의 경우 요소에 무작위로 액세스하면 배열이 빨라지고 새로운 요소를 추가 (추가)하면 목록이 빨라집니다. 그것들을 반복하는 것은 비슷합니다.


@ leonm-apols, 나는 OP가 * Buffer 클래스에 대해 독점적으로 요구한다고 생각했으며, 그들은 또한 "정상적인"것에 대해서도 묻는다는 것을 알고 있습니다!
oxbow_lakes

2
목록은 래퍼 객체를 생성해야하는 반면, ArrayBuffer는 객체를 평균 (평균 약 2 배) 새로운 배열로 복사하면되기 때문에 일반적으로 ArrayBuffer에 추가하는 것이 목록 앞에 추가하거나 ListBuffer에 요소를 추가하는 것보다 빠릅니다. . 두 개의 복사본은 일반적으로 하나의 객체 생성보다 빠르므로 ArrayBuffer 추가는 일반적으로 List 접두사보다 우선합니다.
Rex Kerr

iterate over캐시 때문에 어레이가리스트보다 훨씬 빠르게 수행
Bin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.