JavaRush /Java Blog /Random-KO /그림의 Java ArrayList

그림의 Java ArrayList

Random-KO 그룹에 게시되었습니다
안녕하세요! 오늘 강의는 ArrayList이전 강의에 비해 한편으로는 간단하면서도 한편으로는 더 어려울 것입니다. 그림의 작업 ArrayList - 1오늘은 "내부"를 살펴보고 ArrayList작업 중에 어떤 일이 일어나는지 연구하기 때문에 더 어렵습니다. 반면에, 이번 강의에는 코드가 거의 없을 것입니다. 대부분 그림과 설명입니다. 자, 가봅시다 :) 이미 알고 있듯이 ArrayList'a 내부에는 데이터 저장소 역할을 하는 일반 배열이 있습니다. 대부분의 경우 목록의 정확한 크기를 지정하지 않습니다. 하지만 내부 배열에는 어느 정도의 크기가 있어야 합니다! 이것은 사실이다. 기본 크기는 [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);//добавляем ford в ячейку 1, которая уже занята
}
이번에도 먼저 배열에 충분한 공간이 있는지 확인합니다. 공간이 충분하면 새 요소를 삽입하는 셀부터 요소가 오른쪽으로 이동됩니다 . 인덱스 1을 사용하여 셀에 붙여넣습니다. 즉, 셀 3의 요소가 셀 4에, 요소 2가 셀 3에, 요소 1이 셀 2에 복사됩니다. 그림의 작업 ArrayList - 4그런 다음 새 요소가 제자리에 붙여넣어집니다. 이전 요소( bugatti)는 이미 해당 위치에서 새 위치로 복사되었습니다. 그림의 작업 ArrayList - 5이제 배열에 삽입할 공간이 없으면 이 프로세스가 어떻게 발생하는지 알아 보겠습니다. 그림의 작업 ArrayList - 6물론, 먼저 충분한 공간이 있는지 확인합니다. 공간이 부족하다고 판단되면 ArrayList'a' 내부에 (OldArray의 크기 * 1.5) + 1 크기의 새로운 배열이 생성되는데, 우리의 경우 새 배열의 크기는 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까지 (공식에 따라 (기존 배열의 크기 * 1.5) + 1)
당연히 이는 리소스 측면에서 상당히 비쌉니다. 따라서 저장된 요소의 일부(적어도 대략적인) 수를 이미 알고 있는 경우 특정 크기의 배열로 목록을 즉시 생성하는 것이 좋습니다.
ArrayList<Car> cars = new ArrayList<>(100);
이제 100개 요소의 배열이 메모리에 즉시 할당되며, 이는 확장 시 리소스가 낭비되지 않으므로 더욱 효율적입니다. 동전의 반대편도 있습니다. 내부 배열 에서 객체를 제거해도 ArrayList크기가 자동으로 줄어들지 않습니다. ArrayList예를 들어, 완전히 채워진 88개 요소의 내부 배열이 있습니다 . 그림의 작업 ArrayList - 13프로그램이 작동하는 동안 77개 요소를 제거하고 11개만 남습니다. 그림의 작업 ArrayList - 14문제가 무엇인지 이미 짐작하셨나요? 물론, 메모리를 비효율적으로 사용합니다! 우리는 11개의 셀만 사용하는 반면 88개의 요소에 메모리를 할당했습니다. 이는 필요한 것보다 8배 더 많은 것입니다! 이 경우 최적화를 수행하려면 특수 클래스 메소드인 를 사용할 수 ArrayList있습니다 trimToSize(). 내부 배열의 길이를 현재 배열에 저장된 요소 수로 "절단"합니다. 그림의 작업 ArrayList - 15이제 필요한 만큼의 메모리가 할당됩니다! :)
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION