[Java ] 개념노트 48 List와 ArrayList 이해하기

[Java 개념노트 48] List와 ArrayList 이해하기

안녕하세요. Java 개념노트 시리즈 마흔여덟 번째 글입니다.

지난 글에서는 여러 데이터를 저장하고 관리하는 컬렉션 프레임워크의 큰 그림을 정리했습니다. 이번 글에서는 그중에서도 가장 자주 사용하는 구조인 ListArrayList에 대해 알아보겠습니다.

List는 순서가 있는 데이터 목록을 다룰 때 사용합니다. 게시글 목록, 상품 목록, 댓글 목록, 검색 결과, 장바구니 목록처럼 여러 데이터를 순서대로 저장해야 할 때 자주 사용됩니다.


1. List란?

List는 데이터를 순서대로 저장하는 컬렉션입니다. 저장한 순서가 유지되고, 같은 값을 여러 번 저장할 수 있습니다.

쉽게 말하면
List는 순서가 있는 데이터 목록입니다. 배열처럼 인덱스로 접근할 수 있지만, 배열보다 추가와 삭제가 더 편리합니다.

List 특징

1. 저장 순서가 유지된다.
2. 중복 값을 허용한다.
3. 인덱스로 값에 접근할 수 있다.
4. 데이터 추가와 삭제가 편리하다.

2. ArrayList란?

ArrayList는 List를 구현한 대표적인 클래스입니다. 자바에서 목록 형태의 데이터를 다룰 때 가장 많이 사용하는 컬렉션 중 하나입니다.

배열은 크기가 고정되어 있지만, ArrayList는 값을 추가하면 내부적으로 크기를 조절하면서 데이터를 저장할 수 있습니다. 그래서 데이터 개수가 변하는 상황에서 배열보다 편하게 사용할 수 있습니다.

List        → 목록 구조의 규칙
ArrayList   → List 규칙을 실제로 구현한 클래스

3. ArrayList import하기

ArrayListjava.util 패키지에 있습니다. 사용하려면 파일 위쪽에 import를 작성해야 합니다.

import java.util.ArrayList;

만약 List 타입으로 선언하고 싶다면 List도 함께 import합니다.

import java.util.List;
import java.util.ArrayList;

4. ArrayList 만들기

문자열을 저장하는 ArrayList는 다음과 같이 만들 수 있습니다.

ArrayList<String> list = new ArrayList<>();

<String>은 이 ArrayList에 문자열만 저장하겠다는 뜻입니다. 이처럼 컬렉션에 저장할 데이터 타입을 지정하는 문법을 제네릭이라고 합니다.

코드 의미
ArrayList<String> 문자열을 저장하는 ArrayList 타입
list ArrayList를 가리키는 변수 이름
new ArrayList<>() 새 ArrayList 객체 생성

5. List 타입으로 선언하기

ArrayList는 보통 다음처럼 List 타입으로도 많이 선언합니다.

List<String> list = new ArrayList<>();

왼쪽은 인터페이스인 List, 오른쪽은 실제 구현 클래스인 ArrayList입니다. 처음에는 아래처럼 이해하면 됩니다.

List<String> list = new ArrayList<>();

List       → 목록으로 다루겠다
ArrayList  → 실제 저장 방식은 ArrayList를 쓰겠다

핵심 포인트
처음에는 ArrayList<String>으로 시작해도 괜찮습니다. 조금 익숙해지면 List<String> list = new ArrayList<>(); 형태도 함께 익히면 좋습니다.

6. add()로 값 추가하기

add()는 ArrayList에 값을 추가할 때 사용합니다.

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();

        list.add("Java");
        list.add("Spring");
        list.add("SQL");

        System.out.println(list);
    }
}

실행 결과는 다음과 같습니다.

[Java, Spring, SQL]

값을 추가한 순서대로 저장되었습니다.

7. List는 중복을 허용한다

List는 같은 값을 여러 번 저장할 수 있습니다.

ArrayList<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("Java");

System.out.println(list);

실행 결과는 다음과 같습니다.

[Java, Spring, Java]

"Java"를 두 번 추가했기 때문에 두 번 저장됩니다. 중복을 막고 싶다면 List가 아니라 Set을 고려해야 합니다.

8. get()으로 값 꺼내기

get()은 특정 인덱스에 있는 값을 꺼낼 때 사용합니다. ArrayList의 인덱스도 배열처럼 0부터 시작합니다.

ArrayList<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("SQL");

System.out.println(list.get(0));
System.out.println(list.get(1));
System.out.println(list.get(2));

실행 결과는 다음과 같습니다.

Java
Spring
SQL

list.get(0)은 첫 번째 값인 "Java"를 반환합니다.

9. size()로 개수 확인하기

size()는 ArrayList에 저장된 값의 개수를 반환합니다.

ArrayList<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("SQL");

System.out.println(list.size());

실행 결과는 다음과 같습니다.

3

배열은 길이를 확인할 때 length를 사용했지만, ArrayList는 메서드인 size()를 사용합니다.

구분 길이 확인
배열 arr.length
ArrayList list.size()

10. set()으로 값 수정하기

set()은 특정 인덱스의 값을 다른 값으로 변경할 때 사용합니다.

ArrayList<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("SQL");

list.set(1, "Spring Boot");

System.out.println(list);

실행 결과는 다음과 같습니다.

[Java, Spring Boot, SQL]

1번 인덱스에 있던 "Spring""Spring Boot"로 바뀌었습니다.

11. remove()로 값 삭제하기

remove()는 값을 삭제할 때 사용합니다. 인덱스로 삭제할 수도 있고, 값을 직접 지정해서 삭제할 수도 있습니다.

인덱스로 삭제하기

ArrayList<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("SQL");

list.remove(1);

System.out.println(list);

실행 결과는 다음과 같습니다.

[Java, SQL]

값으로 삭제하기

ArrayList<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("SQL");

list.remove("SQL");

System.out.println(list);

실행 결과는 다음과 같습니다.

[Java, Spring]

12. Integer 리스트에서 remove 주의하기

ArrayList<Integer>에서 remove()를 사용할 때는 주의해야 합니다. 숫자를 넣으면 값이 아니라 인덱스로 해석될 수 있습니다.

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>();

        numbers.add(10);
        numbers.add(20);
        numbers.add(30);

        numbers.remove(1);

        System.out.println(numbers);
    }
}

실행 결과는 다음과 같습니다.

[10, 30]

numbers.remove(1)은 값 1을 삭제하는 것이 아니라 1번 인덱스의 값인 20을 삭제합니다.

20을 직접 삭제하고 싶다면 다음처럼 Integer.valueOf()를 사용할 수 있습니다.

numbers.remove(Integer.valueOf(20));

주의
ArrayList<Integer>에서 remove(1)은 값 1 삭제가 아니라 1번 인덱스 삭제입니다. 숫자 값을 삭제하려면 Integer.valueOf(값)을 사용하면 안전합니다.

13. contains()로 포함 여부 확인하기

contains()는 특정 값이 ArrayList 안에 있는지 확인합니다. 결과는 true 또는 false입니다.

ArrayList<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("SQL");

System.out.println(list.contains("Java"));
System.out.println(list.contains("Oracle"));

실행 결과는 다음과 같습니다.

true
false

"Java"는 포함되어 있으므로 true이고, "Oracle"은 없으므로 false입니다.

14. indexOf()로 위치 찾기

indexOf()는 특정 값이 처음 등장하는 인덱스를 반환합니다. 값이 없으면 -1을 반환합니다.

ArrayList<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("SQL");

System.out.println(list.indexOf("Spring"));
System.out.println(list.indexOf("Oracle"));

실행 결과는 다음과 같습니다.

1
-1

"Spring"은 1번 인덱스에 있고, "Oracle"은 없으므로 -1입니다.

15. isEmpty()와 clear()

isEmpty()는 ArrayList가 비어 있는지 확인합니다. clear()는 ArrayList 안의 모든 값을 삭제합니다.

ArrayList<String> list = new ArrayList<>();

System.out.println(list.isEmpty());

list.add("Java");
list.add("Spring");

System.out.println(list.isEmpty());

list.clear();

System.out.println(list);
System.out.println(list.isEmpty());

실행 결과는 다음과 같습니다.

true
false
[]
true

16. for문으로 ArrayList 반복하기

ArrayList는 인덱스로 접근할 수 있으므로 일반 for문으로 반복할 수 있습니다.

ArrayList<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("SQL");

for (int i = 0; i < list.size(); i++) {
    System.out.println(i + ": " + list.get(i));
}

실행 결과는 다음과 같습니다.

0: Java
1: Spring
2: SQL

배열과 다르게 반복 조건에는 list.length가 아니라 list.size()를 사용합니다.

17. 향상된 for문으로 반복하기

인덱스가 필요 없다면 향상된 for문을 사용할 수 있습니다.

ArrayList<String> list = new ArrayList<>();

list.add("Java");
list.add("Spring");
list.add("SQL");

for (String item : list) {
    System.out.println(item);
}

실행 결과는 다음과 같습니다.

Java
Spring
SQL

값을 하나씩 꺼내서 읽기만 할 때는 향상된 for문이 간단합니다.

18. ArrayList에 객체 저장하기

ArrayList에는 문자열이나 숫자뿐만 아니라 직접 만든 객체도 저장할 수 있습니다.

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<Product> products = new ArrayList<>();

        products.add(new Product("키보드", 50000));
        products.add(new Product("마우스", 30000));

        for (Product product : products) {
            product.printInfo();
        }
    }
}

class Product {
    String name;
    int price;

    Product(String name, int price) {
        this.name = name;
        this.price = price;
    }

    void printInfo() {
        System.out.println(name + ": " + price + "원");
    }
}

실행 결과는 다음과 같습니다.

키보드: 50000원
마우스: 30000원

ArrayList<Product>Product 객체만 저장하는 목록입니다.

19. ArrayList와 배열 비교

배열과 ArrayList를 비교하면 다음과 같습니다.

구분 배열 ArrayList
크기 처음 정하면 변경하기 어려움 데이터 추가에 따라 유연하게 사용 가능
값 추가 인덱스를 직접 관리해야 함 add() 사용
값 삭제 직접 처리해야 함 remove() 사용
길이 확인 length size()
기본 자료형 저장 int[] 가능 ArrayList<Integer> 사용

20. ArrayList 주요 메서드 정리

자주 사용하는 ArrayList 메서드는 다음과 같습니다.

메서드 역할 예시
add() 값 추가 list.add("Java")
get() 값 꺼내기 list.get(0)
set() 값 수정 list.set(0, "Spring")
remove() 값 삭제 list.remove(0)
size() 개수 확인 list.size()
contains() 포함 여부 확인 list.contains("Java")
indexOf() 값의 위치 확인 list.indexOf("Java")
isEmpty() 비어 있는지 확인 list.isEmpty()
clear() 전체 삭제 list.clear()

21. List와 ArrayList 전체 예제

이번에는 ArrayList의 주요 메서드를 함께 사용하는 전체 예제를 보겠습니다.

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> subjects = new ArrayList<>();

        subjects.add("Java");
        subjects.add("Spring");
        subjects.add("SQL");

        System.out.println("처음 목록: " + subjects);

        subjects.set(1, "Spring Boot");
        System.out.println("수정 후: " + subjects);

        subjects.remove("SQL");
        System.out.println("삭제 후: " + subjects);

        System.out.println("개수: " + subjects.size());
        System.out.println("Java 포함 여부: " + subjects.contains("Java"));
        System.out.println("Java 위치: " + subjects.indexOf("Java"));

        for (int i = 0; i < subjects.size(); i++) {
            System.out.println((i + 1) + "번째 과목: " + subjects.get(i));
        }
    }
}

실행 결과는 다음과 같습니다.

처음 목록: [Java, Spring, SQL]
수정 후: [Java, Spring Boot, SQL]
삭제 후: [Java, Spring Boot]
개수: 2
Java 포함 여부: true
Java 위치: 0
1번째 과목: Java
2번째 과목: Spring Boot

22. List와 ArrayList 사용 시 자주 하는 실수

List와 ArrayList를 처음 사용할 때는 아래와 같은 실수를 자주 합니다.

실수 문제점 해결 방법
import 누락 ArrayList 클래스를 찾지 못함 import java.util.ArrayList; 작성
ArrayList<int> 사용 기본 자료형은 제네릭에 직접 사용 불가 ArrayList<Integer> 사용
list.length 사용 ArrayList에는 length가 없음 list.size() 사용
인덱스 범위 초과 IndexOutOfBoundsException 발생 가능 인덱스는 0부터 size() - 1까지 사용
ArrayList<Integer>에서 remove(값) 착각 숫자가 인덱스로 해석될 수 있음 remove(Integer.valueOf(값)) 사용

23. 직접 연습해보기

아래 코드를 직접 작성하고 실행해보세요.

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> menus = new ArrayList<>();

        menus.add("김밥");
        menus.add("라면");
        menus.add("돈가스");
        menus.add("라면");

        System.out.println("전체 메뉴: " + menus);
        System.out.println("메뉴 개수: " + menus.size());

        System.out.println("라면 포함 여부: " + menus.contains("라면"));
        System.out.println("돈가스 위치: " + menus.indexOf("돈가스"));

        menus.set(0, "참치김밥");
        System.out.println("수정 후: " + menus);

        menus.remove("라면");
        System.out.println("라면 하나 삭제 후: " + menus);

        for (int i = 0; i < menus.size(); i++) {
            System.out.println((i + 1) + ". " + menus.get(i));
        }
    }
}

실행 결과는 다음과 같습니다.

전체 메뉴: [김밥, 라면, 돈가스, 라면]
메뉴 개수: 4
라면 포함 여부: true
돈가스 위치: 2
수정 후: [참치김밥, 라면, 돈가스, 라면]
라면 하나 삭제 후: [참치김밥, 돈가스, 라면]
1. 참치김밥
2. 돈가스
3. 라면

remove("라면")은 처음 발견한 "라면" 하나만 삭제합니다. 그래서 뒤쪽의 "라면"은 남아 있습니다.

24. 이번 글 정리

이번 글에서는 순서 있는 데이터 목록을 다루는 ListArrayList에 대해 정리했습니다. 핵심 내용은 다음과 같습니다.

  • List는 순서가 있는 데이터 목록이다.
  • List는 중복 값을 허용한다.
  • ArrayList는 List의 대표적인 구현 클래스이다.
  • ArrayList를 사용하려면 java.util.ArrayList를 import한다.
  • add()는 값을 추가한다.
  • get()은 인덱스로 값을 꺼낸다.
  • set()은 특정 인덱스의 값을 수정한다.
  • remove()는 값을 삭제한다.
  • size()는 저장된 값의 개수를 반환한다.
  • contains()는 값 포함 여부를 확인한다.
  • indexOf()는 값의 위치를 반환한다.
  • clear()는 모든 값을 삭제한다.
  • ArrayList의 인덱스도 0부터 시작한다.
  • 기본 자료형을 저장하려면 Integer, Double 같은 Wrapper 클래스를 사용한다.

한 줄 요약
ArrayList는 순서가 있고 중복을 허용하는 데이터 목록을 배열보다 편하게 추가, 조회, 수정, 삭제할 수 있게 해주는 대표적인 List 구현 클래스입니다.

다음 글 예고
다음 글에서는 [Java 개념노트 49] Set과 HashSet 이해하기라는 주제로 중복을 허용하지 않는 데이터 저장 구조를 자세히 정리해보겠습니다.

GWDEVELBlog Java 개념노트 시리즈