일반적으로 배열이라는 자료 구조의 개념은 동일한 크기의 메모리 공간이 빈틈없이 연속적으로 나열된 자료 구조를 말한다. 즉, 배열의 요소는 하나의 타입으로 통일되어 있으며 서로 연속적으로 인접해 있다. 이러한 배열을 밀집 배열(dense array)이라 한다.
이처럼 배열의 요소는 동일한 크기를 갖으며 빈틈없이 연속적으로 이어져 있으므로 아래와 같이 인덱스를 통해 단 한번의 연산으로 임의의 요소에 접근(임의 접근(random access), 시간 복잡도 O(1))할 수 있다. 이는 매우 효율적이며 고속으로 동작한다.
검색 대상 요소의 메모리 주소 = 배열의 시작 메모리 주소 + 인덱스 * 요소의 바이트 수
예를 들어, 위 그림처럼 메모리 주소 1000에서 시작하고 각 요소의 크기가 8byte인 배열을 생각해 보자.
- 인덱스가 0인 요소의 메모리 주소 : 1000 + 0 * 8 = 1000
- 인덱스가 1인 요소에 메모리 주소 : 1000 + 1 * 8 = 1008
- 인덱스가 2인 요소에 메모리 주소 : 1000 + 2 * 8 = 1016
이처럼 배열은 인덱스를 통해 효율적으로 요소에 접근할 수 있다는 장점이 있다. 하지만 정렬되지 않은 배열에서 특정한 값을 탐색하는 경우, 모든 배열 요소를 처음부터 값을 발견할 때까지 차례대로 탐색(선형 탐색(linear search), 시간 복잡도 O(n))해야 한다.
또한 배열에 요소를 삽입하거나 삭제하는 경우, 배열 요소를 연속적으로 유지하기 위해 요소를 이동시켜야 하는 단점도 있다.
자바스크립트의 배열은 지금까지 살펴본 일반적인 의미의 배열과 다르다. 즉, 배열의 요소를 위한 각각의 메모리 공간은 동일한 크기를 갖지 않아도 되며 연속적으로 이어져 있지 않을 수도 있다. 배열의 요소가 연속적으로 이어져 있지 않는 배열을 희소 배열(sparse array)이라 한다.
이처럼 자바스크립트의 배열은 엄밀히 말해 일반적 의미의 배열이 아니다. 자바스크립트의 배열은 일반적인 배열의 동작을 흉내낸 특수한 객체이다. 아래 예제를 살펴보자.
console.log(Object.getOwnPropertyDescriptors([1, 2, 3]));
/*
{
'0': { value: 1, writable: true, enumerable: true, configurable: true },
'1': { value: 2, writable: true, enumerable: true, configurable: true },
'2': { value: 3, writable: true, enumerable: true, configurable: true },
length: { value: 3, writable: true, enumerable: false, configurable: false }
}
*/
이처럼 자바스크립트 배열은 인덱스를 프로퍼티 키로 갖으며 length 프로퍼티를 갖는 특수한 객체이다. 자바스크립트 배열의 요소는 사실 프로퍼티 값이다. 자바스크립트에서 사용할 수 있는 모든 값은 객체의 프로퍼티 값이 될 수 있으므로 어떤 타입의 값이라도 배열의 요소가 될 수 있다.
const arr = [
'string',
10,
true,
null,
undefined,
NaN,
Infinity,
[ ],
{ },
function () {}
];
일반적인 배열과 자바스크립트 배열의 장단점을 정리해보면 아래와 같다.
- 일반적인 배열은 인덱스로 배열 요소에 빠르게 접근할 수 있다. 하지만 특정 요소를 탐색하거나 요소를 삽입 또는 삭제하는 경우에는 효율적이지 않다.
- 자바스크립트 배열은 해시 테이블로 구현된 객체이므로 인덱스로 배열 요소에 접근하는 경우, 일반적인 배열보다 성능적인 면에서 느릴 수 밖에 없는 구조적인 단점을 갖는다. 하지만 특정 요소를 탐색하거나 요소를 삽입 또는 삭제하는 경우에는 일반적인 배열보다 빠른 성능을 기대할 수 있다.
즉, 자바스크립트 배열은 인덱스로 배열 요소에 접근하는 경우에는 일반적인 배열보다 느리지만 특정 요소를 탐색하거나 요소를 삽입 또는 삭제하는 경우에는 일반적인 배열보다 빠르다. 자바스크립트 배열은 인덱스로 접근하는 경우의 성능 대신 특정 요소를 탐색하거나 배열 요소를 삽입 또는 삭제하는 경우의 성능을 선택한 것이다.
이처럼 인덱스로 배열 요소에 접근할 때 일반적인 배열보다 느릴 수 밖에 없는 구조적인 단점을 보완하기 위해 대부분의 모던 자바스크립트 엔진은 배열을 일반 객체와 구별하여 보다 배열처럼 동작하도록 최적화하여 구현하였다.
아래와 같이 배열과 일반 객체의 성능을 테스트 해보면 배열이 일반 객체보다 약 2배 정도 빠른 것을 알 수 있다.
const arr = [];
console.time('Array Performance Test');
for (let i = 0; i < 10000000; i++) {
arr[i] = i;
}
console.timeEnd('Array Performance Test');
// 약 340ms
const obj = {};
console.time('Object Performance Test');
for (let i = 0; i < 10000000; i++) {
obj[i] = i;
}
console.timeEnd('Object Performance Test');
// 약 600ms
최신 자바스크립트 엔진에서 Array를 최적화 구현하는 법.
최신 JavaScript 엔진에서 배열은 특히 일반 개체와 비교할 때 효율적으로 수행되도록 최적화되고 구현됩니다. 배열은 JavaScript의 객체이지만 순서가 지정된 데이터 컬렉션을 저장하고 조작하는 데 적합한 고유한 특성을 가지고 있습니다. 최신 JavaScript 엔진의 배열에 대한 자세한 설명과 내부 작동 원리를 살펴보겠습니다.
1. 배열 요소 및 인덱싱:
- 연속 메모리: 내부적으로 배열은 요소를 저장하기 위해 연속 메모리를 할당합니다. 이는 보다 분산된 메모리 할당 전략을 사용하는 일반 개체와 대조됩니다.
- 색인화된 액세스: 배열은 정수 기반 인덱스를 사용하여 요소에 액세스합니다. 첫 번째 요소의 인덱스는 0이고 두 번째 요소의 인덱스는 1입니다. 이를 통해 해당 인덱스를 사용하여 요소에 지속적으로 액세스할 수 있습니다.
2. 희소 배열과 밀도가 높은 배열:
- 밀도 배열: 배열 요소가 연속적으로 할당되고 인덱스 사이에 간격이 없으면 배열이 밀도가 높은 것으로 간주됩니다. 고밀도 어레이는 메모리 사용량과 액세스 시간을 최적화합니다.
- 희소 배열: 간격이 있거나 정의되지 않은 요소가 있는 배열은 희소한 것으로 간주됩니다. JavaScript는 희소 배열을 허용하지만 일반적으로 밀도가 높은 배열이 더 성능이 좋습니다.
3. 배열 길이 속성:
- 길이 속성: 배열에는 배열의 요소 수를 나타내는 '길이' 속성이 있습니다. 'length' 속성은 요소가 추가되거나 제거될 때 자동으로 업데이트됩니다.
- 길이 설정: length 속성을 수동으로 설정하여 배열을 자르거나 확장할 수 있습니다. 새 길이가 현재 길이보다 작으면 배열이 잘립니다. 더 크면 정의되지 않은 요소가 추가됩니다.
4. 어레이 방법 및 최적화:
- 배열 방법: 배열에는 내장된 방법 세트가 함께 제공됩니다(예: push, pop, shift, unshift, splice, map, filter, Reduce 등)을 일반적인 작업에 사용합니다. 이러한 메서드는 고도로 최적화되어 있으며 종종 네이티브 코드로 구현됩니다.
- 반복 방법: 최신 엔진은 종종 배열 반복을 위해 고도로 최적화된 알고리즘을 사용하므로 forEach 및 map과 같은 방법을 매우 효율적으로 만듭니다.
5. 숨겨진 클래스 및 인라인 캐싱:
- 숨겨진 클래스: JavaScript 엔진은 숨겨진 클래스를 사용하여 개체 속성 액세스를 최적화합니다. 구조와 속성 순서가 동일한 배열은 히든 클래스를 공유하여 속성 액세스 비용을 줄여 성능을 향상시킵니다.
- 인라인 캐싱: JavaScript 엔진은 인라인 캐싱을 사용하여 속성 액세스를 최적화합니다. 속성 액세스 패턴이 일관되면 엔진은 액세스 경로를 최적화하여 성능을 향상할 수 있습니다.
6. 형식화된 배열:
- 형식 배열: ECMAScript 6에 도입된 형식형 배열은 요소에 대해 고정된 유형의 배열을 제공합니다(예: Int8Array, Float64Array). 이러한 배열은 낮은 수준의 데이터로 작업할 때 사용되며 특정 작업에 더 나은 성능을 제공합니다.
7. 객체 배열 최적화:
- 빠른 요소와 느린 요소: JavaScript의 배열은 다양한 유형의 요소를 저장할 수 있습니다. 배열에 특정 유형(예: 객체)의 요소만 포함된 경우 엔진은 해당 특정 유형에 최적화된 "빠른 요소" 표현을 사용할 수 있습니다.
8. 성능 고려 사항:
- 성능을 위해 희소 배열 방지: JavaScript는 희소 배열을 허용하지만 일반적으로 조밀한 배열은 최적화된 메모리 액세스 패턴으로 인해 더 나은 성능을 발휘합니다.
- 배열 방법 선호: 내장된 배열 방법을 사용하는 것이 수동으로 배열을 반복하는 것보다 성능이 더 좋은 경우가 많습니다.
9. V8 엔진(크롬에서 사용):
- V8 엔진 최적화: Chrome에서 사용되는 V8 엔진은 숨겨진 클래스, 인라인 캐싱, 다양한 시나리오에 대한 특수 배열 표현을 포함하여 배열 성능을 위한 다양한 최적화를 사용합니다.
JavaScript 엔진에서 배열의 내부 작동을 이해하면 개발자는 보다 효율적인 코드를 작성하고 특정 사용 사례에 배열을 사용하여 얻을 수 있는 성능 이점을 활용할 수 있습니다. 엔진 구현은 다양할 수 있으며 br마다 최적화가 다를 수 있다는 점에 유의하는 것이 중요합니다.
희소 배열의 희소성의 영향을 최소화하는 전략
JavaScript 엔진에서는 데이터 구조와 최적화 기술의 조합을 통해 희소 배열 처리의 효율성을 달성합니다. 비어 있지 않은 슬롯 사이에 구멍이나 정의되지 않은 요소가 있는 희소 배열은 본질적으로 조밀한 배열보다 효율성이 떨어지지만 최신 엔진은 희소성의 영향을 최소화하는 전략을 구현합니다. 희소 배열의 내부 작동 원리와 최적화를 살펴보겠습니다.
1. 인덱싱된 속성 및 요소:
- 인덱싱된 속성 저장: 배열을 포함한 JavaScript 객체에서 속성은 명명된 속성(일반 객체 속성과 같은) 또는 인덱싱된 속성(숫자 인덱스가 있는 배열의 경우)으로 저장될 수 있습니다.
- 요소 종류: 배열은 포함된 요소 유형에 따라 다양한 "요소 종류"를 가질 수 있습니다. 예를 들어, 구멍과 작은 정수 요소가 있는 배열의 경우 배열에 "HOLEY_SMI_ELEMENTS"의 "ElementsKind"가 있을 수 있습니다.
2. 요소 전환:
- 종류 간 전환: JavaScript 엔진은 "요소 전환" 개념을 사용하여 배열 구조의 변경 사항을 동적으로 처리합니다. 요소가 추가되거나 제거되면 엔진은 액세스 패턴을 최적화하기 위해 배열을 다른 요소 종류로 전환할 수 있습니다.
- 효율적인 표현: 엔진은 배열의 현재 구조에 가장 효율적인 요소 종류를 선택합니다. 예를 들어 조밀한 배열은 연속 인덱스에 최적화된 표현을 사용할 수 있는 반면, 희소 배열은 정의되지 않은 요소를 보다 효율적으로 처리하는 표현을 사용할 수 있습니다.
3. 백킹 스토어:
- 백킹 저장소: 엔진은 종종 "빠른 요소" 백업 저장소와 "사전 요소" 백업 저장소의 조합을 사용합니다. "빠른 요소" 저장소는 연속 인덱스가 있는 조밀한 배열에 사용되는 반면, "사전 요소" 저장소는 연속되지 않는 인덱스가 있는 희소 배열에 사용됩니다.
3. 백업 저장소:
3.1 빠른 요소 백업 스토리지(고집적 어레이):
- 고밀도 배열: 요소에 연속 인덱스가 있고 간격이 없는 밀도 배열의 맥락에서 JavaScript 엔진은 종종 "빠른 요소" 지원 스토리지를 사용합니다.
- 연속 메모리 할당: "빠른 요소" 백업 저장소는 요소가 연속 메모리 위치에 저장되는 경우 효율성을 위해 설계되어 정수 인덱스를 기반으로 빠르고 직접적인 액세스가 가능합니다.
- 최적화된 액세스: 조밀한 배열을 사용하면 인덱스가 연속적이며 엔진은 간단한 산술을 사용하여 요소의 메모리 주소를 계산할 수 있으므로 일정한 시간 액세스가 가능합니다.
3.2 사전 요소 백업 스토리지(희소 어레이):
- 희소 배열: 비어 있지 않은 슬롯 사이에 간격이나 정의되지 않은 요소가 포함된 희소 배열은 메모리 사용량과 액세스 시간을 최적화하기 위해 다른 접근 방식이 필요합니다.
- 사전 요소 백업 스토리지: 희소 배열의 경우 엔진은 "사전 요소" 백업 스토리지 메커니즘을 사용할 수 있습니다. 즉, 엔진은 가능한 모든 인덱스에 메모리를 할당하는 대신 명시적으로 정의되거나 할당된 요소에만 메모리를 할당합니다.
- 메모리 효율성: 정의된 요소에만 메모리를 할당함으로써 엔진은 정의되지 않거나 빈 슬롯에서 메모리가 낭비되는 것을 방지합니다. 이 접근 방식은 배열에 희박하거나 연속되지 않은 인덱스가 있는 시나리오에서 메모리 효율성이 더 높습니다.
- 동적 조정: 엔진은 어레이 구조에 따라 스토리지 전략을 동적으로 조정합니다. 어레이가 고밀도에서 희소로 또는 그 반대로 전환되면 엔진은 이에 따라 백업 스토리지를 조정할 수 있습니다.
예시 시나리오:
다음 예를 고려하십시오.
고밀도 배열:
const denseArray = [10, 20, 30, 40, 50];
빠른 요소 백업 스토리지: 엔진은 각 요소에 연속적인 메모리 위치를 할당하여 빠르고 직접적인 액세스를 허용합니다.
희소 배열:
const sparseArray = [];
sparseArray[0] = "apple";
sparseArray[1000] = "banana";
- 사전 요소 지원 스토리지: 엔진은 명시적으로 정의된 요소(인덱스 0 및 1000)에 대해서만 메모리를 할당하여 정의되지 않은 요소가 있는 경우 메모리 사용량을 최적화합니다.
요약:
"빠른 요소"와 "사전 요소" 지원 스토리지의 조합을 통해 JavaScript 엔진은 다양한 배열 구조에 효율적으로 적응할 수 있습니다. 조밀한 배열은 빠른 액세스를 위해 연속적인 메모리 할당의 이점을 누리는 반면, 희소 배열은 명시적으로 정의된 요소에만 스토리지를 할당하여 메모리 사용을 최적화합니다. 이러한 저장 메커니즘의 동적 특성은 JavaScript의 배열 작업의 전반적인 성능에 기여합니다.
4. 숨겨진 클래스 및 인라인 캐싱:
- 숨겨진 클래스: 숨겨진 클래스의 개념은 인덱싱된 속성에 대한 액세스를 최적화하는 데 여전히 중요합니다. 유사한 구조를 가진 배열은 속성 액세스 속도를 높이기 위해 숨겨진 클래스를 공유합니다.
- 인라인 캐싱: 속성 액세스를 최적화하기 위해 인라인 캐싱이 사용됩니다. 속성 액세스 패턴이 일관되면 엔진은 인라인 캐싱을 사용하여 액세스 경로를 최적화할 수 있습니다.
5. 지도 전환:
- 맵 전환: Chrome에서 사용되는 V8 엔진은 배열에 '맵 전환' 메커니즘을 사용합니다. 배열의 구조가 변경되면(예: 구멍이 추가되는 경우) 엔진은 현재 구조를 더 잘 나타내는 새 맵으로 전환할 수 있습니다.
6. 반복 처리:
- 반복 작업: 희소 배열에 대한 효율적인 반복은 정의되지 않은 요소가 있기 때문에 어렵습니다. 엔진은 구멍을 반복할 필요 없이 배열에 대한 반복을 처리하기 위해 특수 메커니즘을 사용합니다.
- 더 스마트한 반복: 배열의 빈 부분을 건너뛰고 정의된 요소만 반복하도록 반복 작업이 구현됩니다.
7. 성능에 미치는 영향:
- 희소 배열 고려 사항: 엔진은 희소 배열 처리를 최적화하지만, 개발자는 희소 배열에 대한 반복이 특히 조밀한 배열에 비해 여전히 성능에 영향을 미칠 수 있다는 점을 인식해야 합니다.
예시 시나리오:
다음 희소 배열을 고려해보세요.
const sparseArray = [];
sparseArray[0] = "apple";
sparseArray[1000] = "banana";
- 내부적으로 엔진은 숨겨진 클래스, 요소 종류 전환 및 적절한 백업 저장소의 조합을 사용하여 연속되지 않은 인덱스와 정의되지 않은 요소를 효율적으로 처리하는 표현을 선택할 수 있습니다.
- sparseArray[0] 및 sparseArray[1000]과 같은 요소에 액세스하는 것은 배열 구조에 따라 최적화됩니다.
최적화 및 내부 메커니즘은 JavaScript 엔진마다 다를 수 있다는 점에 유의하는 것이 중요합니다. 엔진 구현은 지속적으로 개선되며 브라우저 공급업체에 따라 다를 수 있습니다. 이러한 원칙을 이해하면 개발자가 희소성의 잠재적 영향을 고려하면서 배열의 성능 이점을 활용하는 코드를 작성하는 데 도움이 됩니다.
조밀한 배열에 삽입:
- 끝에 삽입:
- 조밀한 배열의 끝에 요소를 삽입하는 것은 인접한 메모리 블록의 끝에 요소를 추가하는 것과 관련되므로 일반적으로 효율적입니다. 이 연산은 일정한 시간복잡도 O(1)을 갖습니다.
- 시작 또는 중간에 삽입:
- 조밀한 배열의 시작 또는 중간에 요소를 삽입하려면 새 요소를 위한 공간을 확보하기 위해 모든 후속 요소를 이동해야 합니다. 이 연산의 시간 복잡도는 O(n)입니다. 여기서 n은 배열의 요소 수입니다.
조밀한 배열의 삭제:
- 종료 시 삭제:
- 조밀한 배열의 끝에서 요소를 삭제하는 것은 인접한 메모리 블록에서 마지막 요소를 제거하는 작업을 포함하므로 일반적으로 효율적입니다. 이 연산은 일정한 시간복잡도 O(1)을 갖습니다.
- 처음 또는 중간부터 삭제:
- 조밀한 배열의 시작 또는 중간에서 요소를 삭제하려면 제거된 요소가 남긴 간격을 채우기 위해 모든 후속 요소를 이동해야 합니다. 이 연산의 시간 복잡도는 O(n)입니다. 여기서 n은 배열의 요소 수입니다.
절충안:
- 고밀도 배열의 장점:
- "빠른 요소" 지원 스토리지를 갖춘 고밀도 배열은 인덱스를 사용하여 요소에 대한 빠르고 지속적인 액세스를 제공합니다.
- 연속적인 메모리 할당으로 인해 Random Access 및 Iteration이 효율적입니다.
- 삽입 및 삭제 제한사항:
- 특히 조밀한 배열 중간에서의 삽입 및 삭제에는 요소 이동이 포함되며 특히 배열 크기가 커질수록 효율성이 떨어질 수 있습니다.
제한 완화 전략:
- 연결된 목록 사용:
- 빈번한 삽입과 삭제가 주요 관심사라면 연결 목록이 더 적합한 데이터 구조일 수 있습니다. 연결된 목록은 어떤 위치에서든 지속적인 삽입과 삭제를 제공합니다.
- 접속 방법:
- JavaScript에서는 조밀한 배열에서 효율적인 삽입 및 삭제를 위해 splice 메소드를 사용할 수 있습니다. 배열 변경을 시작할 인덱스, 제거할 요소 수 및 추가할 요소를 지정할 수 있습니다.
- 장단점 고려:
- 애플리케이션의 특정 요구 사항에 따라 데이터 구조를 선택하십시오. 무작위 액세스와 반복이 더 일반적인 작업인 경우 조밀한 배열이 적합할 수 있습니다. 빈번한 삽입과 삭제가 중요한 경우 다른 데이터 구조를 고려하십시오.
요약하자면, 조밀한 배열은 임의 액세스 및 반복에 이점을 제공하지만 요소 이동이 필요하기 때문에 삽입 및 삭제의 효율성이 떨어질 수 있습니다. 데이터 구조 선택은 애플리케이션이 가장 자주 수행하는 작업 유형 간의 균형에 따라 달라집니다.
{
0 : 'a',
1 : 'b',
2 : 'c',
3 : 'd'
}
가 있고 1에 e를 추가하면 e에 1이되고 나머지 b,c,d는 index가 하나씩 밀려서 다른 dense array와 성능이 같이 않을까? 궁금하였습니다.
JavaScript 배열의 특정 인덱스에 요소를 삽입한 후 새 요소를 수용하도록 배열의 크기를 조정하면 결과 구조가 조밀한 배열의 구조와 유사할 수 있다고 합니다.
위의 예를 분석해보면
const array = [1, 2, 3, 4];
인덱스 '1'에 값 '5'를 삽입
array.splice(1, 0, 5);
// Result: [1, 5, 2, 3, 4]
이제 배열은 [1, 5, 2, 3, 4]가 되었습니다. 인덱스를 보면 0, 1, 2, 3, 4로 여전히 연속되어 있습니다. 이는 인덱스가 연속적이므로 밀집된 배열과 유사합니다.
그러나 JavaScript 배열은 유연하며 구현 시 내부적으로 메모리와 인덱싱을 다르게 처리할 수 있다는 점에 유의하는 것이 중요합니다. 삽입 후 인덱스가 연속적으로 보이더라도 기본 메커니즘은 엄격한 고정 크기의 연속 메모리 배열을 사용하는 언어와 동일하지 않을 수 있습니다.
JavaScript에서 유연성은 배열이 객체에 더 가깝고 인덱스가 속성 키라는 사실에서 비롯됩니다. 이는 희소 배열뿐만 아니라 동적 크기 조정 및 기타 편리한 기능을 허용합니다. 배열의 동작은 특정 사용 사례에 맞게 최적화될 수 있지만 메모리 모델이 다른 언어의 배열과 동일하게 동작한다고 보장할 수는 없습니다.
요약하자면, 특정 작업 후에는 결과가 조밀한 배열과 유사하게 나타날 수 있지만 JavaScript 배열의 기본 메커니즘과 유연성은 더 엄격한 메모리 마나를 가진 언어의 배열과 다릅니다.
JAVA는 희소배열을 지원하지 않는다
Java에서 배열의 동작은 명시적으로 정의되었는지 여부에 관계없이 모든 요소에 대해 메모리가 할당되는 것입니다. JavaScript 또는 Python과 같은 다른 언어와 달리 Java 배열은 명시적으로 정의된 요소에 대해서만 메모리를 할당한다는 의미에서 본질적으로 희소 배열을 지원하지 않습니다.
다음은 Java의 예입니다.
public class SparseArrayExample {
public static void main(String[] args) {
String[] sparseArray = new String[1000];
sparseArray[0] = "apple";
// Memory is allocated for indices 1, 2, 3, ..., even though they are undefined
sparseArray[1000] = "banana";
}
}
이 Java 예제에서는 새로운 문자열 배열(new String[1000])을 생성할 때 값이 할당되거나 null로 남아 있는지 여부에 관계없이 모든 1000개 요소에 대해 메모리가 할당됩니다. 이는 명시적으로 정의된 요소에만 메모리가 할당되는 다른 언어와 다릅니다.
Java의 희소 배열과 더 유사한 데이터 구조가 필요한 경우 가능한 모든 인덱스에 메모리를 할당하지 않고 값을 특정 인덱스와 연결할 수 있는 'Map' 또는 유사한 데이터 구조를 사용하는 것을 고려할 수 있습니다. 다음은 HashMap을 사용한 예입니다.
import java.util.HashMap;
import java.util.Map;
public class SparseArrayExample {
public static void main(String[] args) {
Map<Integer, String> sparseArray = new HashMap<>();
sparseArray.put(0, "apple");
// No memory is allocated for indices 1, 2, 3, ...
sparseArray.put(1000, "banana");
}
이 예에서 HashMap은 명시적으로 정의된 인덱스에 대해서만 메모리를 할당하여 희소 데이터 구조에 대해 보다 메모리 효율적인 접근 방식을 제공합니다.
'javascript Deep Dive' 카테고리의 다른 글
[Javascript] Web API (0) | 2023.12.29 |
---|---|
[Javascript] Promise (0) | 2023.12.29 |
[Javascript] var, let, const 차이점과 각각의 사용 이유 (1) | 2023.12.29 |
[Javascript] map vs for(각 특징과 map의 장점) (0) | 2023.12.28 |
[Javascript] Javascript vs Java 웹사이트 채택이유 (1) | 2023.12.28 |