JavaRush /Java Blog /Random-KO /new ArrayList(????) 초기화하는 방법과 위치가 더 낫습니다.
Vovan
레벨 22

new ArrayList(????) 초기화하는 방법과 위치가 더 낫습니다.

Random-KO 그룹에 게시되었습니다
컬렉션 프레임워크를 사용하지 않고 코드를 작성하는 것은 미친 짓입니다. 이것은 많은 깔끔한 솔루션을 갖춘 훌륭한 Java 제품입니다. 더 중요한 것은 배열과 달리 크기에 대해 걱정할 필요가 없다는 것입니다. ArrayList는 메모리가 부족할 때까지 증가합니다. 개발자는 초기 크기와 ArrayIndexOutOfBoundsException 오류 에 대해 걱정할 필요가 없습니다 . 그런데 메모리 양을 모니터링하는 조건이 있다면 어떨까요? 컬렉션 작업 시 메모리를 효율적으로 사용할 수 있나요?
표준적인 질문이 생깁니다: 목록을 어떻게 초기화합니까? 아래 코드는 작동하지 않습니다. 컴파일 오류가 발생합니다. 지역 변수 이름이 초기화 되지 않았을 수 있습니다 . Java 사양에서는 모든 지역 변수(스택에 존재하는 변수)가 적절한 값으로 초기화되도록 요구합니다. 이를 수행하는 방법은 다음과 같습니다. 의심할 여지없이 목록을 초기화해야 합니다. 첫 번째 줄에서 목록을 만들 수도 있고, getAllNames() 메서드 에서 했던 것처럼 좀 더 스마트하게 초기화 초기화를 사용할 수도 있습니다 . 이 경우 목록은 필요할 때만 생성됩니다. 초기 조건이 충족되지 않으면 목록이 힙에 나타나지 않습니다. 여기서 우리는 주요 질문에 도달합니다: 목록에 대해 어떤 크기를 설정해야 합니까? 가장 좋은 방법은 그에게 정확한 크기를 알려주는 것입니다. 예: 이 경우 정확히 n개의 이름이 반환되어야 하며 결과적으로 n개의 요소 컬렉션이 생성됩니다. 그러나 n 의 정확한 값이 항상 알려진 것은 아닙니다. 주어진 예에서도 n=1000 이고 사용 가능한 이름이 100개뿐이라면 어떻게 될까요? 컬렉션 작업 시 가장 널리 사용되는 방법은 기본 생성자를 호출하는 것입니다. 자바 소스코드(버전 1.6)를 보면 알 수 있듯이 기본적으로 10개의 요소 목록이 생성된다 . 즉, 목록에 10개 이상의 요소를 저장할 계획이 없을 때 기본 생성자를 안전하게 사용할 수 있습니다. 11번째 요소를 추가하려고 하면 어떻게 되나요? 음, 나쁘지는 않습니다... 요소가 성공적으로 추가될 것입니다. 메소드를 살펴보세요. 배열의 크기는 verifyCapacity 메소드 에 의해 제어됩니다 . 크기가 1.5배 증가합니다 . 새로운 배열이 생성되고 요소가 그 배열로 이동됩니다. 크기를 10으로 설정하면 11번째 요소는 다음과 같습니다.
public List getAllNames() { List names; if (/*необходимые условия выполнены*/) { names = new ArrayList (); /*заполнение списка*/ } return names; }
List names = null; List names = new ArrayList (); List names = new ArrayList (0); List names = new ArrayList (size);
public List getTopNames (int n) { List names = null; if ( /*необходимые условия выполнены*/) { names = new ArrayList (n); /*заполнение списка*/ } return names; }
names = new ArrayList ();

/** * Конструирует пустой список с указанной начальной емкостью. * * @param initialCapacity начальная емкость списка * @exception IllegalArgumentException если указанная начальная емкость отрицательна * */ public ArrayList(int initialCapacity) { super(); if (initialCapacity < 0) this.elementData = new Object[initialCapacity]; } /** * Конструирует пустой список с начальной емкостью, равной 10. */ public ArrayList() { this(10); }
public Boolean add(E e) { ensureCapacity(size + 1); //увеличивает modCount!! elementData[size++] = e; return true; } public void ensureCapacity (int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { throw new IllegalArgumentException(“Illegal Capacity: ” + initialCapacity); Object oldData[] = elementData; int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // minCapacity обычно ближе к размеру, так что это беспроигрышно: elementData = Arrays.copyOf(elementData, newCapacity); } }
  • 크기가 10 * 3 / 2 + 1 = 16으로 변경됩니다.
  • 다음 증가 = 16 * 3 / 2 + 1 = 25
  • 다음 증가 = 25 * 3 / 2 + 1 = 39 등등.
요소가 100개인 경우 JVM은 새 배열을 여러 번 생성하고 해당 배열에 요소를 복사해야 합니다. 이를 고려하여 필요한 어레이 크기에 대한 가정이 있는 경우 초기 용량을 이에 가깝게 설정하는 것이 좋습니다. 다음은 조치에 대한 몇 가지 지침입니다.
  1. 필요할 때만 컬렉션을 만들고 , 그렇지 않으면 null로 초기화하거나 Collections.EMPTY_LIST를 사용하세요 .
  2. 필요한 정확한 크기를 알고 있는 경우 컬렉션 생성자에 이를 지정하세요.
  3. 요소 수가 10개를 초과하지 않을 것이라고 확신하는 경우 기본 생성자를 사용해도 됩니다.
  4. 크기가 0인 컬렉션을 만드는 것과 관련된 위험은 새 배열을 만들고 데이터를 복사하는 빈도가 더 높아질 수 있다는 것입니다. 크기가 0인 컬렉션을 사용하는 이점이 실제로 그렇게 큰지 매우 신중하게 생각해야 합니다 .
  5. 메서드 시작 부분에서 너무 큰 컬렉션을 초기화했는데 이를 줄이고 싶다면 TrimToSize() 메서드가 있습니다 .
물론 이러한 지침은 배열 기반 컬렉션으로 작업할 때 적용되며 연결된 목록의 경우에는 이 중 어느 것도 의미가 없습니다. 실제로 이러한 문제가 프로그램을 죽이는 요인이 될 가능성은 없지만 조금 더 나은 결과를 얻을 수 있는 기회가 있다면 사용하는 것은 어떨까요? 다른 유용한 팁이 있나요? 일을 더 잘 할 수 있는 방법을 찾았나요? 아니면 이 모든 것이 불필요합니까? 어떻게 생각하나요?
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION