ToBe끝판왕

[ JAVA ] 컬렉션 프레임워크 (1) - List 본문

■ 프로그래밍 SKILLS/JAVA

[ JAVA ] 컬렉션 프레임워크 (1) - List

업그레이드중 2024. 10. 23. 01:21
반응형

 

 


 

 

컬렉션 프레임워크 - 배열 리스트

 

 

 

1) 배열이란 ?

 

 

▶ 배열 리스트에 대하여 알아보기 전, 배열에 대하여 먼저 파악하자 !

 

• 배열의 특징

-  배열의 길이  :  .length 속성을 통해서 얻을 수 있다.

-  배열은 for 반복문과 자주 사용 ( 모든 요소를 순회할 수 있다. )

 

-  고정된 크기 : 배열을 한 번 생성하면 크기가 고정, 변경 불가능 ( 배열의 크기는 선언 시, 결정 )

-  동일한 데이터 타입 : 한가지 타입의 데이터만 저장 가능

   ( 다른 타입의 데이터를 저장하기 위해서는 Object 배열 혹은 제네릭 컬렉션 사용해야 한다.

-  인덱스를 사용한 접근 : 배열의 각 요소는 0부터 시작하는 인덱스를 통해 접근 가능

 

 

• 배열에서는 Index를 사용하면 자료를 매우 빠르게 찾을 수 있다.

-  배열의 시작 참조( x100 ) + ( 자료의 크기( 4byte) * 인덱스 위치(2)) = x108

-  참조 x108 에 있는 값 10을 찾을 수 있다.

 

 

• 배열의 한계점

-  배열은 인덱스를 사용할 때 최고의 효율이 나온다.

-  단점은 배열의 크기를 배열을 생성하는 시점에 미리 정한다는 점 ( = 정적으로 길이가 정해져 있다. )

-  길이가 정해져 있기 때문에 데이터를 추가하기 불편

 

 

=>  동적으로 언제든지 길이를 늘리고 줄일 수 있는 자료구조의 필요성

 

 


 

 

2) List 자료구조의 등장

 

 

• List 자료구조의 특징

- 요소가 추가된 순서를 유지 ( 인덱스를 통해서 요소에 접근 가능 )

-  중복 허용 ( 동일한 값 여러번 저장 가능 )

-  배열과 같이 인덱스를 사용하여 요소에 접근 가능 ( 0부터 시작한다. )

 

 

• 자바의 컬렉션 프레임워크가 제공하는 가장 대표적인 자료구조가 리스트이다.

- 리스트와 관련된 컬렉션 프레임워크는 아래와 같은 구조를 가진다.

 

 

※  Collection 인터페이스

-  Java.util 패키지의 컬렉션 프레임워크의 핵심 인터페이스 중 하나

-  자바에서 다양한 컬렉션, 즉 데이터 그룹을 다루기 위한 메서드를 정의

-  List, Set, Queue 등 다양한 하위 인터페이스들과 같이 사용되어 데이터를 해당 형태로 관리한다.

 

 

• List 인터페이스의 주요 메서드

메서드 설명
add ( E element ) 리스트의 끝에 지정된 요소를 추가
get ( int index ) 리스트에서 지정된 위치의 요소를 반환
set ( int index, E element ) 지정한 위치의 요소를 변경, 이전 요소를 반환
remove ( int index ) 지정된 위치의 요소를 제거하고 그 요소를 반환
clear() 리스트에서 모든 요소를 반환
size() 리스트의 요소 수를 반환
isEmpty() 리스트가 비어있는지 여부를 반환

 

 


 

 

• 자바 ArrayList의 특징

-  배열을 사용해서 데이터 관리

-  기본 CAPACITY는 10, CAPACITY를 넘어가면 배열을 50% 증가

-  메모리 고속 복사 연산을 사용 

 

 

• 자바 LinkedList의 특징

-  이중 연결 리스트 구조 ( 다음 노드 뿐만 아니라 이전 노드로도 이동 가능 )

-  첫번째 노드와 마지막 노드 둘다 참조

 

 

 

• 자바 제공 리스트의 성능 비교

 

package hello.blog;

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

public class JavaListTest {

    public static void main(String[] args) {

        int size = 50_000;

        System.out.println("== ArrayList 추가 ==");
        addFirst(new ArrayList<>(), size);
        addMid(new ArrayList<>(), size);
        ArrayList<Integer> arrayList = new ArrayList<>();   // 조회용 데이터로 사용
        addLast(arrayList, size);

        System.out.println("== LinkedList 추가 ==");
        addFirst(new LinkedList<>(), size);
        addMid(new LinkedList<>(), size);
        ArrayList<Integer> linkedList = new ArrayList<>();   // 조회용 데이터로 사용
        addLast(linkedList, size);

        int loop = 10000;
        System.out.println("== ArrayList 조회 ==");
        getIndex(arrayList, loop,0);
        getIndex(arrayList, loop, size / 2);
        getIndex(arrayList, loop, size -1);

        System.out.println("== LinkedList 조회 ==");
        getIndex(linkedList, loop,0);
        getIndex(linkedList, loop, size / 2);
        getIndex(linkedList, loop, size -1);

        System.out.println("== ArrayList 검색 ==");
        search(arrayList, loop,0);
        search(arrayList, loop, size / 2);
        search(arrayList, loop, size -1);

        System.out.println("== LinkedList 검색 ==");
        search(linkedList, loop,0);
        search(linkedList, loop, size / 2);
        search(linkedList, loop, size -1);

    }

    private static void addFirst(List<Integer> list, int size) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < size; i++ ) {
            list.add(0, i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("앞에 추가 - 크기: " + size + ", 계산 시간 : " + (endTime - startTime) + "ms");
    }

    private static void addMid( List<Integer> list, int size) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < size; i++ ) {
            list.add(i / 2, i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("평균 추가 - 크기: " + size + ", 계산 시간 : " + (endTime - startTime) + "ms");
    }

    private static void addLast(List<Integer> list, int size) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < size; i++ ) {
            list.add(i);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("뒤에 추가 - 크기: " + size + ", 계산 시간 : " + (endTime - startTime) + "ms");
    }

    private static void getIndex(List<Integer> list, int loop, int index) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < loop; i++ ) {
            list.get(index);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("index: " + index + ", 반복: " + loop +  ", 계산 시간 : " + (endTime - startTime) + "ms");
    }

    private static void search(List<Integer> list, int loop, int findValue) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < loop; i++ ) {
            list.indexOf(findValue);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("findValue: " + findValue + ", 반복: " + loop +  ", 계산 시간 : " + (endTime - startTime) + "ms");
    }
}

 


// 결과

== ArrayList 추가 ==
앞에 추가 - 크기: 50000, 계산 시간 : 130ms
평균 추가 - 크기: 50000, 계산 시간 : 62ms
뒤에 추가 - 크기: 50000, 계산 시간 : 2ms
== LinkedList 추가 ==
앞에 추가 - 크기: 50000, 계산 시간 : 2ms
평균 추가 - 크기: 50000, 계산 시간 : 1125ms
뒤에 추가 - 크기: 50000, 계산 시간 : 2ms
== ArrayList 조회 ==
index: 0, 반복: 10000, 계산 시간 : 0ms
index: 25000, 반복: 10000, 계산 시간 : 0ms
index: 49999, 반복: 10000, 계산 시간 : 0ms
== LinkedList 조회 ==
index: 0, 반복: 10000, 계산 시간 : 0ms
index: 25000, 반복: 10000, 계산 시간 : 0ms
index: 49999, 반복: 10000, 계산 시간 : 1ms
== ArrayList 검색 ==
findValue: 0, 반복: 10000, 계산 시간 : 0ms
findValue: 25000, 반복: 10000, 계산 시간 : 129ms
findValue: 49999, 반복: 10000, 계산 시간 : 317ms
== LinkedList 검색 ==
findValue: 0, 반복: 10000, 계산 시간 : 0ms
findValue: 25000, 반복: 10000, 계산 시간 : 134ms
findValue: 49999, 반복: 10000, 계산 시간 : 273ms



// 추가, 삭제
- 배열리스트 : 인덱스를 통해 추가 및 삭제 위치는 빠르게 찾지만 추가 및 삭제 이후 데이터 이동에
              오래 걸린다.
- 연결리스트 : 인덱스를 통해 추가 및 삭제 위치는 느리게 찾지만, 실제 데이터의 추가는
              간단한 참조 변경으로 빠르게 수행된다.

 

 

• ArrayList 와 LinkedList

대부분의 경우, 성능상 ArrayList가 유리하기 때문에 실무에서는 주로 배열리스트를 사용한다.

-  But, 데이터를 앞쪽에 자주 추가하거나 삭제할 일이 있을 경우 연결리스트의 사용도 고려함이 옳다. 

 

 

- ArrayList의 사용 예시


// ( 예시 1 )

package hello.blog;

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

public class ArrayListEx01 {

    public static void main(String[] args) {

        List<Integer> students = new ArrayList<>();
        students.add(90);
        students.add(80);
        students.add(70);
        students.add(60);
        students.add(50);

        int total = 0;
        for ( int i = 0; i < students.size(); i++ ) {
            total += students.get(i);
        }

        double average = (double) total / students.size();
        System.out.println("점수 총합 : " + total);
        System.out.println("점수 평균 : " + average);
    }
}

 

 


// 결과

점수 총합 : 350
점수 평균 : 70.0

 

 


// ( 예시 2 )

package hello.blog;

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

public class ArrayListEx02 {

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        List<Integer> numbers = new ArrayList<>();

        System.out.println("n개의 정수를 입력하세요 ( 종료 0 ) ");
        while (true) {
            int input = scanner.nextInt();
            if(input == 0 ) {
                break;
            }
            numbers.add(input);
        }

        System.out.print("출력: ");
        for ( int i = 0; i < numbers.size(); i++ ) {
            System.out.print(numbers.get(i));
            if( i < numbers.size() - 1 ) {
                System.out.print(", ");
            }
        }
    }
}

 

// 결과

n개의 정수를 입력하세요 ( 종료 0 ) 
1
2
3
4
5
0
출력: 1, 2, 3, 4, 5

 

 


// ( 예시 3 - 쇼핑카트 )

package hello.blog.Ex3;

public class Item {

    private String name;
    private int price;
    private int quantity;

    public Item(String name, int price, int quantity) {
        this.name = name;
        this.price = price;
        this.quantity = quantity;
    }

    public String getName() {
        return name;
    }

    public int getTotalPrice() {
        return price * quantity;
    }
}

 

package hello.blog.Ex3;

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

public class ShoppingCart {

    private List<Item> items = new ArrayList<>();


    public void addItem(Item item) {
        items.add(item);
    }

    public void displayItems() {
        System.out.println("장바구니 상품 출력");
        for (Item item : items) {
            System.out.println("상품명: " + item.getName() + ", 합계: " + item.getTotalPrice());
        }
        System.out.println("전체 가격 합: " + calculateTotalPrice());
    }

    private int calculateTotalPrice() {
        int totalPrice = 0;
        for (Item item : items) {
            totalPrice += item.getTotalPrice();
        }
        return totalPrice;
    }
}

 

package hello.blog.Ex3;

public class ShoppingCartMain {

    public static void main(String[] args) {

        ShoppingCart cart = new ShoppingCart();

        Item item1 = new Item("마늘", 2000, 2);
        Item item2 = new Item("상추", 3000, 4);

        cart.addItem(item1);
        cart.addItem(item2);

        cart.displayItems();
    }
}

 

 

• List의 이점

-  자료구조의 크기가 동적으로 증가한다.

-  리스트는 size() 를 통해 입력된 데이터의 크기를 제공

 

 

 

※ 해당 내용은 인프런 김영한 강사님의  "실전 자바 중급2" 인강의 자료와 예시들을 참고하였습니다

반응형
Comments