๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๋นˆ ๊ตฌ๋ฉ ์ฑ„์šฐ๊ธฐ

[Java] ArrayList ๋‚ด๋ถ€ ๊ตฌํ˜„

์ถœ์ฒ˜

ChatGPT


ArrayList๋Š” Java์˜ java.util ํŒจํ‚ค์ง€์—์„œ ์ œ๊ณตํ•˜๋Š” ๋™์  ๋ฐฐ์—ด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ์ปฌ๋ ‰์…˜ ํด๋ž˜์Šค์ด๋‹ค. ArrayList๋Š” ๋ฐฐ์—ด์„ ๋‚ด๋ถ€์ ์œผ๋กœ ์‚ฌ์šฉํ•˜์—ฌ ์š”์†Œ๋“ค์„ ์ €์žฅํ•˜๋ฉฐ, ํ•„์š”์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์†Œ์Šค ์ฝ”๋“œ ์˜ˆ์ œ๋Š” Java 8 ๋ฒ„์ „์˜ ArrayList ์†Œ์Šค ์ฝ”๋“œ ๋ถ€๋ถ„๋“ค์ด๋‹ค. 

 

 

1. ๊ธฐ๋ณธ ๊ตฌ์กฐ

ArrayList๋Š” List ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉฐ, ๋‚ด๋ถ€์ ์œผ๋กœ ๋™์  ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์š”์†Œ๋“ค์„ ์ €์žฅํ•œ๋‹ค. ์ด ๋ฐฐ์—ด์€ ํ•„์š”์— ๋”ฐ๋ผ ์ž๋™์œผ๋กœ ํฌ๊ธฐ๊ฐ€ ์กฐ์ •๋œ๋‹ค.

์ฃผ์š” ํ•„๋“œ

// ๊ธฐ๋ณธ์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋Š” ๋นˆ ๋ฐฐ์—ด๋กœ, ์ดˆ๊ธฐ ์ƒํƒœ์—์„œ ๋น„์–ด์žˆ๋Š” ArrayList๋Š” ์ด ๋ฐฐ์—ด์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.
private static final Object[] EMPTY_ELEMENTDATA = {};

// ๋นˆ ๋ฐฐ์—ด์ด์ง€๋งŒ, ์ดˆ๊ธฐ ์šฉ๋Ÿ‰์ด ์ง€์ •๋œ ArrayList๋Š” ์ด ๋ฐฐ์—ด์„ ์ฐธ์กฐํ•ฉ๋‹ˆ๋‹ค.
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

// ์‹ค์ œ ๋ฐ์ดํ„ฐ๊ฐ€ ์ €์žฅ๋˜๋Š” ๋ฐฐ์—ด
transient Object[] elementData;

// ArrayList์˜ ํฌ๊ธฐ(ํ˜„์žฌ ์ €์žฅ๋œ ์š”์†Œ์˜ ์ˆ˜)
private int size;

 

elementData ๋ฐฐ์—ด์€ Object ํƒ€์ž…์˜ ๋ฐฐ์—ด๋กœ, ๋ชจ๋“  ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋Š” ํ˜•ํƒœ์ด๋‹ค. ํ•˜์ง€๋งŒ, ์›์‹œ ํƒ€์ž…์€ ์ €์žฅํ•  ์ˆ˜ ์—†๊ณ , ๋ฐ˜๋“œ์‹œ ํ•ด๋‹น ํƒ€์ž…์˜ ๋ž˜ํผ ํด๋ž˜์Šค (์˜ˆ: Integer, Double)๋กœ ์ €์žฅ๋œ๋‹ค.

 

2. ์ƒ์„ฑ์ž

ArrayList๋Š” ๋‹ค์–‘ํ•œ ์ƒ์„ฑ์ž๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

๊ธฐ๋ณธ ์ƒ์„ฑ์ž

๋‚ด๋ถ€ ๋ฐฐ์—ด์˜ ์ดˆ๊ธฐ ํฌ๊ธฐ๊ฐ€ 10์ธ ๊ธฐ๋ณธ ์šฉ๋Ÿ‰์œผ๋กœ ์ƒ์„ฑ๋œ๋‹ค.

public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

 

์ดˆ๊ธฐ ์šฉ๋Ÿ‰์„ ์ง€์ •ํ•˜๋Š” ์ƒ์„ฑ์ž

์‚ฌ์šฉ์ž๊ฐ€ ์ดˆ๊ธฐ ์šฉ๋Ÿ‰์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

public ArrayList(int initialCapacity) {
    if (initialCapacity > 0) {
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
    } else {
        throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
    }
}

 

์ปฌ๋ ‰์…˜์„ ์ธ์ž๋กœ ๋ฐ›๋Š” ์ƒ์„ฑ์ž

๋‹ค๋ฅธ ์ปฌ๋ ‰์…˜์„ ์ธ์ž๋กœ ๋ฐ›์•„ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

public ArrayList(Collection<? extends E> c) {
    elementData = c.toArray();
    if ((size = elementData.length) != 0) {
        if (elementData.getClass() != Object[].class)
            elementData = Arrays.copyOf(elementData, size, Object[].class);
    } else {
        this.elementData = EMPTY_ELEMENTDATA;
    }
}

 

3. ํฌ๊ธฐ ์กฐ์ • Resizing

ArrayList์˜ ๊ฐ€์žฅ ์ค‘์š”ํ•œ ํŠน์ง• ์ค‘ ํ•˜๋‚˜๋Š” ๋ฐฐ์—ด์ด ๋™์ ์ด๋ผ๋Š” ๊ฒƒ์ด๋‹ค. ์ฆ‰, ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๊ฐ€ ์ž๋™์œผ๋กœ ์กฐ์ •๋œ๋‹ค. ์ด ์ž‘์—…์€ ์ƒˆ๋กœ์šด ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•  ๋•Œ, ๋‚ด๋ถ€ ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๊ฐ€ ๋ถ€์กฑํ•˜๋ฉด ์ˆ˜ํ–‰๋œ๋‹ค.

 

ํฌ๊ธฐ ์ฆ๊ฐ€ ๋ฉ”์ปค๋‹ˆ์ฆ˜

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
} // ChatGPT์˜ ์ฝ”๋“œ

/** ๋‚ด ์ปดํ“จํ„ฐ Java 8 ์ฝ”๋“œ
private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
**/


private void ensureExplicitCapacity(int minCapacity) {
    // ํฌ๊ธฐ๋ฅผ ์ฆ๊ฐ€ํ•˜๊ธฐ ์ „์— ๊ตฌ์กฐ์  ์ˆ˜์ • ํšŸ์ˆ˜๋ฅผ ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.
    modCount++;

    // ํ•„์š”ํ•œ ์ตœ์†Œ ์šฉ๋Ÿ‰์ด ํ˜„์žฌ ๋ฐฐ์—ด์˜ ๊ธธ์ด๋ณด๋‹ค ํฐ ๊ฒฝ์šฐ ํฌ๊ธฐ ์กฐ์ •
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

private void grow(int minCapacity) {
    int oldCapacity = elementData.length;
    // ํ˜„์žฌ ํฌ๊ธฐ์˜ 1.5๋ฐฐ๋กœ ์ฆ๊ฐ€
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    elementData = Arrays.copyOf(elementData, newCapacity);
}

 

  • ํ˜„์žฌ ํฌ๊ธฐ์˜ 1.5๋ฐฐ๋กœ ์ฆ๊ฐ€: ArrayList๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ํ˜„์žฌ ๋ฐฐ์—ด ํฌ๊ธฐ์˜ 1.5๋ฐฐ๋กœ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆฐ๋‹ค. ์ฆ‰, ๋ฐฐ์—ด์˜ ๊ธธ์ด๋ฅผ ๋Š˜๋ฆด ๋•Œ๋งˆ๋‹ค 50%์”ฉ ์ฆ๊ฐ€ํ•œ๋‹ค.
  • ๋ฐฐ์—ด ๋ณต์‚ฌ: ์ƒˆ๋กœ์šด ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•œ ํ›„, ๊ธฐ์กด ๋ฐฐ์—ด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ƒˆ๋กœ์šด ๋ฐฐ์—ด๋กœ ๋ณต์‚ฌํ•œ๋‹ค.
  • ์ตœ๋Œ€ ํฌ๊ธฐ ๊ฒ€์‚ฌ: JVM์ด ํ—ˆ์šฉํ•˜๋Š” ์ตœ๋Œ€ ๋ฐฐ์—ด ํฌ๊ธฐ๋ฅผ ์ดˆ๊ณผํ•˜์ง€ ์•Š๋„๋ก ๊ฒ€์‚ฌํ•œ๋‹ค.

 

 

4. ์š”์†Œ ์ถ”๊ฐ€ ๋ฐ ์ œ๊ฑฐ

์š”์†Œ ์ถ”๊ฐ€

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // ๋‚ด๋ถ€ ๋ฐฐ์—ด์ด ์ถฉ๋ถ„ํ•œ์ง€ ํ™•์ธ
    elementData[size++] = e;           // ์š”์†Œ๋ฅผ ๋ฐฐ์—ด์— ์ถ”๊ฐ€ํ•˜๊ณ  size๋ฅผ ์ฆ๊ฐ€
    return true;
}

 

  • ์ƒˆ๋กœ์šด ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— ensureCapacityInternal ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ํ˜„์žฌ ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๋ฅผ ํ™•์ธํ•˜๊ณ  ํ•„์š”ํ•˜๋ฉด ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•œ๋‹ค.
  • ์š”์†Œ๋ฅผ elementData ๋ฐฐ์—ด์— ์ถ”๊ฐ€ํ•˜๊ณ , size๋ฅผ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.

์š”์†Œ ์ œ๊ฑฐ

public E remove(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));

    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index + 1, elementData, index, numMoved);

    elementData[--size] = null; // GC(๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜)์„ ๋•๊ธฐ ์œ„ํ•ด ๋งˆ์ง€๋ง‰ ์š”์†Œ๋ฅผ null๋กœ ์„ค์ •

    return oldValue;
} // ChatGPT ์ œ๊ณต ์ฝ”๋“œ

/** ๋‚ด ์ปดํ“จํ„ฐ Java 8 ์ฝ”๋“œ
public E remove(int index) {
    rangeCheck(index);
    modCount++;
    E oldValue = elementData(index);
    int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null; // clear to let GC do its work
    return oldValue;
}

private void rangeCheck(int index) {
    if (index >= size)
        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}

**/

 

 

  • ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•  ๋•Œ, ์ œ๊ฑฐํ•  ์š”์†Œ ๋’ค์— ์žˆ๋Š” ๋ชจ๋“  ์š”์†Œ๋“ค์„ ์™ผ์ชฝ์œผ๋กœ ์ด๋™์‹œํ‚จ๋‹ค.
  • ์ด๋™ ํ›„, ๋งˆ์ง€๋ง‰ ์œ„์น˜์˜ ์š”์†Œ๋Š” null๋กœ ์„ค์ •ํ•˜์—ฌ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

 

 

5. ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜(Garbage Collection) ์ง€์›

ArrayList๋Š” ๋™์  ํฌ๊ธฐ ์กฐ์ •์„ ์œ„ํ•ด ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ, ๋ถˆํ•„์š”ํ•œ ๊ฐ์ฒด๋“ค์ด ๋ฉ”๋ชจ๋ฆฌ์— ๋‚จ์ง€ ์•Š๋„๋ก ๊ด€๋ฆฌํ•ด์•ผ ํ•œ๋‹ค. ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•  ๋•Œ, ํ•ด๋‹น ์ธ๋ฑ์Šค์˜ ๊ฐ’์„ null๋กœ ์„ค์ •ํ•˜์—ฌ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์ด ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ํšŒ์ˆ˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋‹ค.

 

6. ์„ฑ๋Šฅ ํŠน์„ฑ

 

  • ์ธ๋ฑ์Šค ์ ‘๊ทผ(O(1)): ๋ฐฐ์—ด ๊ธฐ๋ฐ˜์ด๊ธฐ ๋•Œ๋ฌธ์— ์ธ๋ฑ์Šค๋ฅผ ์‚ฌ์šฉํ•œ ์ ‘๊ทผ์ด ๋น ๋ฅด๋‹ค.
  • ์š”์†Œ ์ถ”๊ฐ€(O(1) ํ‰๊ท , O(n) ์ตœ์•…): ์ผ๋ฐ˜์ ์œผ๋กœ ๋์— ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์€ ๋น ๋ฅด์ง€๋งŒ, ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋Š๋ ค์งˆ ์ˆ˜ ์žˆ๋‹ค.
  • ์š”์†Œ ์ œ๊ฑฐ(O(n)): ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•  ๋•Œ ๋ฐฐ์—ด์˜ ์š”์†Œ๋“ค์„ ์ด๋™ํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์š”์†Œ๊ฐ€ ๋งŽ์€ ๊ฒฝ์šฐ ๋Š๋ ค์งˆ ์ˆ˜ ์žˆ๋‹ค.