2013-07-04 3 views
0

ArrayList에서 추가 작업은 상각 작업입니다. 그래서 StringBuffer을 읽는 동안 그것은 StringBuffer이 왜 상환되지 않는지 내 마음에 왔습니다. 문자열 버퍼 객체에 추가 작업을 사용한다고 가정하면 기본 배열 구현에 문자를 많이 추가 할 수 있어야합니다. 하지만 그 대신 나는 우리가 문자열 버퍼의 추가 작업에 StringBuffer 및 할부 상화

System.arraycopy(chars, 0, value, count, chars.length); 

이 해당 소스 코드에서 발견했다. 그래서 제 질문은 StringBuffer을 상환하지 않아서 O (N) 복잡성을 줄일 수 있습니까?

+0

'상각 작업'이란 무엇입니까? – Axel

+0

@Axel : [도움을 드리겠습니다.] (http://en.wikipedia.org/wiki/Amortized_analysis) – Makoto

답변

1

하루가 끝날 무렵, 일부 메모리 위치 A에서 다른 메모리 위치 B로 N 개의 참조를 이동합니다. 그러나 나는 확신합니다. System.arraycopy에서 수행하면 StringBuffer에서 성능이 향상됩니다. 그러나, 그것은 당신이 append 또는 insert 일 경우에 달려 있습니다.

ArrayListadd을 수행 할 수있는 두 가지 방법이 있습니다. 하나의 개체를 사용하거나 특정 인덱스 스폿의 요소를 아래로 이동하는 것입니다. 둘 다 다른 공연을합니다.

이 문제를 해결하려면 StringBuffer (System.arraycopy())으로 전화하십시오. 이 구현은 실제로 JVM에 종속적인데 (기본 호출 임), 이 매우 빠름이라는 가능성이 있습니다. 그 외에도 매우 큰 대용량 연속되지 않는 메모리 영역을 제외하고는 StringBuffer.append()의 성능을 실제로 느리게 할 수있는 것은별로 없습니다.

ArrayList.add(E element)은 amoritized O (1) 시간이 걸리지 만 더 많은 요소가 들어갈 수 있도록 backing array를 늘려야 할 가능성 때문에 O (N)으로 바뀔 수 있습니다. 그래도 삽입 할 필요가 없다면 삽입 시간은 O (1) (배열 끝에 요소를 추가하는 순서)입니다.

ArrayList.add(int index, E element)

가능성 O (1) 가장 좋은 경우 만, O - 인한 그것의 E 배치 아래로 이동하는 원소의 양에 평균 최악의 경우 (N 인덱스)

. 이 배열을 복사 않으므로

  • StringBuffer.append() 코드는 amoritized O (N)으로 볼 수있다 : 정리해. 그러나이 작업은 여전히 ​​빠르며 이동하는 데이터가 얼마나 큰지에 따라 달라집니다. StringBuffer.insert()에 대한

  • 코드

  • 는 다른 이며, 쉽게 (1) 최상의 경우에 amoritized O 될 수 있으며, 최악의 O (N) (이 System.arraycopy()- 호출을하기 때문에). 주어진 지점에 요소를 삽입한다는 것은 코드의 속도가 빠르더라도 모든 것을 아래로 이동해야한다는 것을 의미합니다.

내가 사용하는 방법에 따라, 다음 생각, 당신은 amoritized 한 성능을 . 성능이 어떠 할지를 말하기 위해 수행중인 작업을 확인해야합니다.

0

당신은 소스 코드에 더 보면 :

public AbstractStringBuilder append(char[] str) { 
    int len = str.length; 
    ensureCapacityInternal(count + len); // expand array if needed 
    System.arraycopy(str, 0, value, count, len); 
    count += len; 
    return this; 
} 

정확히 어떻게 ArrayList의 작품이다 그.

System.arraycopy(str, 0, value, count, len); 

횟수 (현재 StringBuffer와 종료 위치)에서 시작 값하는 STR로부터 복사 말해 준다. 추가 된 str의 길이 인 len 만 복사됩니다.

+0

이 질문에 대한 답변이 없습니다. 한 장소에서 다른 장소로 문자열을 복사하는 것이 더 많은 메모리를 필요로하며 (작업을 수행하는 동안) 문자열의 모든 요소를 ​​읽는 것을 의미합니다. 이는 복잡성이 o (n)가됨을 의미합니다. –

1

사실 StringBufferArrayList는 동일한 방식으로 작동하고 지적으로, ArrayList에서 add 작업은 O(1)을 상각입니다. 당신이 용량이 충분하지 않은 경우, 새로운 배열을 할당하고 데이터가 복사되도록 요소를 추가 할 때

ArrayList 당신은 또한 ensureCapacity 방법이있다. 그러나이 재 할당 작업은 거의 발생하지 않으므로 K가 1 시간이 걸리더라도 O(n)이 걸리더라도 추가 작업을 수행하려면 O(1)이 필요하다고 생각할 수 있습니다.

+0

ensureCapacity의 코드를 확인한 결과 System.arraycopy (value, 0, newData, 0, count)도 사용한다는 것을 알았습니다. 나는 또한 생각 전체 배열을 새로운 위치로 복사합니다. 그래서 내 이해가 틀렸다면 내 의심은 여전히 ​​정교합니다. –

+0

당신 말이 맞아요. 이것은 기본 배열을 확장해야 할 때 K를 1 회 초과하는 "O (n)"연산입니다. –

0

입력 크기에 따라 데이터 구조 (ArrayList/StringBuilder 길이)의 크기와 복잡성에 따라 복잡도가 혼합됩니다.

ArrayList의 O(1)은 목록의 콘텐츠에 단일 요소를 추가하는 것을 말하며 O(1)의 금액으로 상각됩니다. 분명히 n 요소를 목록에 추가하면 n * O(1)이됩니다. StringBuilder에서도 마찬가지입니다. 대부분의 경우 단일 문자 추가는 O(1)입니다 (내부 배열을 확장해야하는 경우는 제외).하지만 char 배열을 추가하면 배열의 값을 복사해야합니다. 실제로 배열의 대량 복사는 단일 문자를 추가하는 것보다 빠릅니다.

O(1) 링크 목록을 사용하여 추가 할 때 목록 연결이 가능하지만 그 결과는 연결된 하위 목록의 변경에 취약 할 수 있습니다. StringBuilder는 항상 피하기를 원합니다. 구현이 엄청나게 비효율적 일 것입니다.