CodeGym /Java Blog /무작위의 /사진의 ArrayList
John Squirrels
레벨 41
San Francisco

사진의 ArrayList

무작위의 그룹에 게시되었습니다
안녕! 오늘의 수업은 ArrayList이전 수업보다 쉽고 어려울 것입니다.
사진의 ArrayList - 1
오늘 우리는 다양한 작업 중에 일어나는 일을 자세히 살펴보고 ArrayList연구할 것이기 때문에 더 어려울 것입니다. 반면에 이 수업에는 코드가 거의 없습니다. 사진과 설명이 대부분입니다. 글쎄, 가자 :) 이미 알고 있듯이 ArrayList내부에는 데이터 저장소 역할을 하는 일반 배열이 있습니다. 대부분의 경우 목록의 정확한 크기를 지정하지 않습니다. 그러나 내부 배열에는 어느 정도의 크기가 있어야 합니다! 그래서 그렇습니다. 기본 크기는 10 입니다 .

public static void main(String[] args) {
   ArrayList<Car> cars = new ArrayList<>();
}
사진의 ArrayList - 2 먼저 새 요소를 추가하는 모습을 살펴보겠습니다. 비즈니스의 첫 번째 순서는 내부 배열이 내부 배열에 충분한 공간을 가지고 있는지 와 하나 이상의 요소가 맞는지 여부를 확인하는 것입니다 . 공간이 있으면 새 요소가 목록 끝에 추가됩니다. "끝까지"라고 말할 때 배열의 마지막 위치를 의미하는 것은 아닙니다(이상할 것입니다). 마지막 현재 요소 다음의 위치를 ​​의미합니다. 인덱스는 cars.size(). 목록이 현재 비어 있습니다( cars.size() == 0). 따라서 새 요소는 위치 0에 추가됩니다.

ArrayList<Car> cars = new ArrayList<>();
Car ferrari = new Car("Ferrari 360 Spider");
cars.add(ferrari);
사진의 ArrayList - 3 충분히 명확합니다. 중간에, 즉 다른 요소 사이에 삽입하면 어떻게 됩니까?

public static void main(String[] args) {
   ArrayList<Car> cars = new ArrayList<>();
   Car ferrari = new Car("Ferrari 360 Spider");
   Car bugatti = new Car("Bugatti Veyron");
   Car lambo = new Car("Lamborghini Diablo");
   Car ford = new Car("Ford Modneo");
  
   cars.add(ferrari);
   cars.add(bugatti);
   cars.add(lambo);
  
   cars.add(1, ford);// add ford to cell 1, which is already occupied
}
다시 말하지만 먼저 어레이에 충분한 공간이 있는지 확인합니다. 공간이 충분하면 새 요소를 삽입할 위치부터 시작하여 요소가 오른쪽으로 이동합니다 . 우리는 위치 1에 삽입하고 있습니다. 즉, 위치 3의 요소는 위치 4에, 요소 2는 위치 3에, 요소 1은 위치 2에 복사됩니다. 사진의 ArrayList - 4 그런 다음 새 요소가 그 자리에 삽입됩니다. 이전 요소(bugatti)는 이미 거기에서 새 위치로 복사되었습니다. 사진의 ArrayList - 5 이제 배열에 새 요소를 삽입할 위치가 없는 경우 이 프로세스가 어떻게 발생하는지 살펴보겠습니다. 사진의 ArrayList - 6 당연히 충분한 공간이 있는지 먼저 확인해야 합니다. 공간이 충분하지 않으면 내부에 새 어레이가 생성됩니다.ArrayList그 크기는 이전 배열의 크기에 1.5를 더한 값입니다. 우리의 경우 새 배열의 크기는 16이 됩니다. 모든 현재 요소가 즉시 거기에 복사됩니다. 사진의 ArrayList - 7 이전 배열은 가비지 수집기에 의해 삭제되고 새로 확장된 배열만 남습니다. 이제 새로운 요소를 위한 공간이 있습니다. 우리는 그것을 점유된 위치 3에 삽입하고 있습니다. 이제 친숙한 절차가 시작됩니다. 인덱스 3부터 시작하는 모든 요소가 오른쪽으로 한 위치 이동되고 새 요소가 조용히 추가됩니다. 사진의 ArrayList - 8 그리고 삽입이 완료되었습니다! 삽입이 완료되었습니다. 이제 항목 제거 에 대해 이야기하겠습니다 . 배열로 작업할 때 문제가 발생했음을 기억할 것입니다. 요소를 제거하면 배열에 "구멍"이 생깁니다.제거할 때마다 우리는 이 변화를 수행하기 위해 매번 자체 코드를 작성해야 했습니다. ArrayList는 동일한 원칙을 따르지만 이미 이 메커니즘을 구현하고 있습니다. 사진의 ArrayList - 9 이것이 어떻게 생겼는지입니다: 사진의 ArrayList - 10 그리고 결국 우리는 우리가 원하는 것을 얻습니다: 사진의 ArrayList - 11 요소 lambo가 제거되었습니다. 여기에서 우리는 중간에서 요소를 제거했습니다. 분명히 목록의 끝에서 요소를 제거하는 것이 더 빠릅니다. 다른 모든 요소를 ​​이동할 필요 없이 해당 요소가 단순히 제거되기 때문입니다. 내부 배열의 차원과 그것이 메모리에 배열되는 방식에 대해 잠시 다시 이야기합시다. 어레이를 확장하려면 약간의 리소스가 필요합니다. 따라서ArrayList최소 100개의 요소가 있다고 확신하는 경우 기본 크기로 설정합니다. 내부 배열 은 100번째 요소를 삽입할 때까지 6배 확장되어야 하며 모든 요소는 매번 이동해야 합니다.
  • 10개 요소에서 16개 요소로
  • 16개 요소에서 25개 요소로
  • 25에서 38까지
  • 38에서 58까지
  • 58에서 88까지
  • 88에서 133으로(예: 이전 어레이 크기 x 1.5 + 1)
상상할 수 있듯이 이것은 상당히 자원 집약적입니다. 따라서 필요한 항목 수를 이미 대략적으로 알고 있는 경우 특정 크기의 배열로 목록을 만드는 것이 좋습니다.

ArrayList<Car> cars = new ArrayList<>(100);
이제 100개 요소의 배열에 대한 메모리가 한 번에 모두 할당되어 배열을 더 효율적으로 만듭니다(확장할 필요가 없음). 이 전략에는 반전도 있습니다. 에서 객체를 제거해도 ArrayList내부 배열의 크기는 자동으로 줄어들지 않습니다. ArrayList88개의 요소로 구성된 완전한 내부 배열이 있다고 가정합니다 . 사진의 ArrayList - 12 프로그램이 실행될 때 77개의 요소를 제거하므로 11개만 남습니다. 사진의 ArrayList - 13 문제가 무엇인지 이미 짐작하셨습니까? 알겠습니다. 비효율적인 메모리 사용입니다! 여기서는 11개의 위치만 사용하지만 88개 요소에 메모리를 할당했습니다. 그것은 우리가 필요로 하는 것보다 8배 더 많습니다! 이 경우 ArrayList클래스의 특수 메서드 중 하나를 사용하여 메모리 사용을 최적화할 수 있습니다.trimToSize(). 이 메서드는 내부 배열의 길이를 현재 배열에 저장된 요소 수까지 "자릅니다". 사진의 ArrayList - 14 이제 필요한 만큼만 메모리를 할당했습니다! :)
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION