Array(배열), ArrayList

박영준·2022년 11월 23일
1

Java

목록 보기
56/112

Array(배열)

배열은 매우 多 사용된다!

1. 정의

  • 인덱스는 0 부터 시작

  • 같은 타입의 여러 변수를 하나의 묶음으로 저장
    → int배열은 int값만, String 배열은 문자열만 저장

  • 선언과 동시에 저장할 수 있는 타입이 결정
    → 다른 타입의 값을 저장 시, 컴파일 에러

  • 한 번 생성된 배열의 길이는 늘리거나 줄이기 X

    • 만약, 배열의 크기가 부족할 때는?
      • 방법 1 : 필요한 만큼의 크기의 배열을 새롭게 만들기
      • 방법 2 : 새로 만든 배열에 기존 배열의 값을 복사해서 저장

2. 인덱스

  • int[] age = new int[5];
    • 5는 배열의 길이

  • age[3] = 28
    • 배열 age 의 4번째 요소에 28을 저장

  • int beatitudoAge = age[3];
    • 배열 age의 4번째 요소의 값을 읽어서 beatitudoAge 변수에 저장

3. 사용법

1) 배열 선언

// 문법
타입[] 변수; 
타입 변수[];

// 예시
int[] intArray;
int intArray[];

// 타입별로 예시
int[] intArray;    			// 정수 배열
long[] longArray;
double[] doubleArray;  		// 실수 배열 
char[] charArray;  			// 문자 배열
String[] stringArray; 		// 문자열 배열
  • 대괄호[] : 배열 변수 선언하는 기호

  • Java 에서는 배열을 ‘객체’ 취급한다.
    → 따라서, 배열은 힙 영역에 생성되고, 배열 변수는 힙 영역의 배열 객체를 참조 (배열 변수는 참조 변수에 속함)
    (단, 참조할 배열 객체 없다면, null 값도 가질 수 있음)

    참고: this, final, public static void main(String[] args) - (2) Static영역

2) 배열 생성

  1. int[] age;
  • int 타입의 배열을 다루기 위한 참조변수 age 를 선언
  1. age = new int[5];
  • int 타입의 값 5개를 저장할 수 있는 배열을 생성(new)
  1. 배열의 시작 주소(메모리 주소)가 참조변수 age 에 저장된다.
  • 참조변수와 배열이 연결
  • age 는 저장된 주소를 통해 해당 배열을 가리킴

① 값 목록으로 배열 생성

public static void main(String[] args) {

	// int[] scores = new int[]{83, 90, 87}; 	// 원래 형태
	int[] scores = {83, 90, 87};				// new int[] 를 생략해서, 이렇게 줄일 수 있음

	System.out.println("scores[0] : " + scores[0]);
	System.out.println("scores[1] : " + scores[1]);
	System.out.println("scores[2] : " + scores[2]);

	int sum = 0;
	for (int i=0; i<3; i++) {		// 3 대신에, scores.length 가 들어갈 수 있음 (scores 의 길이만큼)
		sum += scores[i]
	}
    
	System.out.println("총합 : " + sum);
	double avg = (dobule) sum / 3;		// 3 대신에, scores.length 가 들어갈 수 있음 (scores 의 길이만큼)
	System.out.println("평균 : " + avg);
}
  • int[] scores = {83, 90, 87};

    • 배열의 생성과 초기화를 한번에 함
  • scores[1] = 90 이지만, 90이 아닌 70으로 바꾸고 싶다면?
    → scores[1] = 70; 으로 대입 연산자를 사용

② new 연산자로 배열 생성

  1. 문법

    타입[] 변수 = new 타입[길이]
     int[] socres = new int[3];
    
     scores[0] = 83;
     scores[1] = 90;
     scores[2] = 75;
    • 이미 배열 변수가 선언된 후에도, new 연산으로 배열 생성 가능
      → new 연산자로 처음 배열 생성 시, 배열은 자동적으로 기본값으로 초기화
      → 따라서, 새로운 값을 저장하려면 대입 연산자(=, +=, -=, *=, /=, %=)를 사용해야 함
    • (= 을 기준으로)
      왼쪽 : 선언
      오른쪽 : 생성
  2. new 연산자

    잘못된 사용
    1) 배열 변수 선언한 후

    int[] scores;

    2) '다른 실행문'에서 중괄호 { } 를 사용한 배열 생성 X

    scores = {83, 90, 87}		// 컴파일 에러

    이를 해결해주는 것이 'new 연산자'

    올바른 사용

    public static void main(String[] args) {
    
        // 배열 변수를 선언
        int[] scores;
    
        // new 연산자로 배열 변수 다시 선언
        scores = new int[] {93, 90, 87};
    
        int sum = 0;
    
        // new 연산자로 배열을 선언해줬기 때문에, for 문에서 scores[i] 를 활용할 수 있게 됨
        for (int i=0; i<3; i++) {
            sum += scores[i];
        }
    
        System.out.println("총합 : " + sum);
    }
  3. new 연산자 + add() 메소드

    잘못된 사용
    1) 배열 변수 선언한 후

    int add(int[] scores) {...}

    2) '다른 실행문'에서 중괄호 { } 를 사용한 배열 생성 X

    int result = add({83, 90, 87});

    int[] scores 에서 변수를 이미 선언했는데, 목록으로 구성된 {83, 90, 87} 을 대입하려하기 때문
    → 즉, 빈 방(빈 배열)을 만들어 뒀는데, 사람(값)을 넣지 않고 빈 방에 빈 방을 넣으려고 한다.

    올바른 사용

    public static void main(String[] args) {
    
        int[] sum = add(new int[] {83, 90, 87});
    
        System.out.println("총합 : " + sum);
    }
    
    public static int add(int[] scores) {
    
        int sum = 0;
    
        for (int i=0; i<3; i++) {
            sum += scores[i];
        }
    
        return sum;
    }

3) 배열의 초기화

(1) 정의

  • 배열의 각 요소에 처음으로 값을 저장하는 것

  • 기본적으로는 각 값의 타입의 기본값으로 자동 초기화된다.(초기값)

  • 배열의 초기값은 타입의 초기값

(2) 방법

// 방법 1
int[] num = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9};

// 방법 2
int[] num = {1, 2, 3, 4, 5, 6, 7, 8, 9};		// new int[] 생략 가능

(3) 배열 초기화

class Arrays2_2 {
    public static void main(String[] args) {
        int[] num1 = new int[]{1,2,3,4,5,6,7,8,9};
        int[] num2 = {1,2,3,4,5,6,7,8,9};

        for (int i = 0; i < num1.length; i++) {
            System.out.println("num1[" +i + "] = " + num1[i]);
        }
        System.out.println();
        for (int i = 0; i < num2.length; i++) {
            System.out.println("num2[" +i + "] = " + num2[i]);
        }

        System.out.println();
        
        // 잘못된 사용 -> 에러 발생
        int[] num3;
        num3 = {1,2,3,4,5,6,7,8,9};

        // 올바른 사용
        int[] num4;
        num4 = new int[]{1,2,3,4,5,6,7,8,9};

        for (int i = 0; i < num4.length; i++) {
            System.out.println("num4[" +i + "] = " + num4[i]);
        }
    }
}

(4) 배열 일괄 초기화

import java.util.Arrays;

public class Arr01 {
    public static void main(String[] args) {
        int[] intArray = {1, 2, 3, 4, 5};

        Arrays.fill(intArray, 1);

        for (int i : intArray) {
            System.out.print(i);
        }
    }
}
  • Arrays.fill(배열, 초기화시킬 값)
    • 해당 배열의 모든 원소를 '초기화시킬 값'으로 모두 일괄적으로 초기화시킨다

4) i < array.length

public static void main(String[] args) {
	int max = 0;
	int[] array = {1, 5, 3, 8, 2};

	for (int i=0; i<array.length; i++) {
		if (max < array[i]) {
			max = array[i];
		}
	}
    
	System.out.println("max: " + max);
}
  • for 문에서 i < array.length : 배열의 마지막 인덱스는 배열 길이 보다 1만큼 적기 때문에, < 연산자 를 사용

  • 길이 : 배열에 저장할 수 있는 전체 항목의 ‘개수’

5) 다차원 배열

public static void main(String[] args) {

	// 다차원 배열 1
	int[][] mathScores = new int[2][3];
    
	for (int i=0; i<mathScores.length; i++) {
		for (int k=0; k<mathScores[i].length; k++) {
			System.out.println("mathScores["+i+"]["+k+"]="+mathScores[i][k]);
		}
	}
	System.out.println();

	// 다차원 배열 2
	int[][] englishScores = new int[2][];
	englishScores[0] = nes int[2];
	englishScores[1] = nes int[3];

	for (int i=0; i<englishScores.length; i++) {
		for (int k=0; k<englishScores[i].length; k++) {
			System.out.println("englishScores["+i+"]["+k+"]="+englishScores[i][k]);
		}
	}
	System.out.println();

	// 다차원 배열 3
	int[][] javaScores = {{95, 80}, {92, 96, 80}};
    
	for (int i=0; i<javaScores.length; i++) {
		for (int k=0; k<javaScores[i].length; k++) {
			System.out.println("javaScores["+i+"]["+k+"]="+javaScores[i][k]);
		}
	}
}
  • 중첩 for 문 사용

  • 배열의 정확한 길이를 알고 인덱스를 사용해야 함
    → 존재하지 않는 인덱스라면, ArrayindexoutofBoundsException 발생

6) 배열 복사

얕은 복사

int[] a = { 1, 2, 3, 4 };
int[] b = a; 		// 얕은 복사 : a와 b 는 동일한 주소값을 바라보게 됨

b[0] = 3; 		// b 배열의 0번째 순번값을 3으로 수정 (1 -> 3)

System.out.println(a[0]);

/* 출력 결과 (a 배열의 0번째 순번값도 3으로 조회됨)
3
*/
  • 대입 연산자 = 를 사용해서 복사를 하게 되면, 주소값만 복사됨

    • 주소값만 복사되고, 실제값은 1개로 유지
  • 참조형

깊은 복사

  • 방법 1 : for 문 을 통해서 하나씩 꺼내서 복사

    int[] a = { 1, 2, 3, 4 };
    int[] b = new int[a.length]; 
    
    for (int i = 0; i < a.length; i++) {
        b[i] = a[i]; 		// 깊은 복사
    }
    
    b[0] = 3;				// b 배열의 0번째 순번값을 3으로 수정 (1 -> 3)
    
    System.out.println(a[0]);
    
    /* 출력 결과
    1
    */
    • 깊은 복사를 했기때문에 a 배열은 그대로 유지
  • 방법 2 : 메서드를 사용

    // 1. clone() 메서드 : 가장 간단한 방법. 그러나, 2차원이상 배열에서는 얕은 복사로 동작
    int[] a = { 1, 2, 3, 4 };
    int[] b = a.clone();
    
    // 2. Arrays.copyOf() 메서드
    int[] a = { 1, 2, 3, 4 };
    int[] b = Arrays.copyOf(a, a.length);		// 배열과 함께 length값도 같이 넣는다.
    
    a[3] = 0;
    System.out.println(a[3]);
    System.out.println(b[0]);
    
    /* 출력 결과 (a만 0으로 바뀌었다)
    0
    4
    */
    • (얕은 복사처럼 가짜 복사가 아닌) 진짜 새로운 배열을 똑같이 만들고 싶을 때 사용

      • 실제 값을 가지고 있는 배열의 기본형 값을 꺼내서 복사
    • 기본형

7) 배열 정렬

(1) 오름차순 정렬

int[] arr = {1, 26, 17, 25, 99, 44, 303};

Arrays.sort(arr);

System.out.println("Sorted arr[] : " + Arrays.toString(arr));

/* 출력 결과
Sorted arr[] : [1, 17, 25, 26, 44, 99, 303] */
  • Arrays.sort()

  • Arrays.toString(배열 이름)

    • 배열의 모든 요소를 문자열로 만들어서 반환
    • (for문으로 출력하는 경우가 아닐 때)
      Arrays.toString 를 사용하지 않고, arr만 출력했을 경우 : 배열이 가리키는 참조변수를 출력해버린다(즉, 주소를 출력)

char[] 을 println() 출력

char[] ch = {'a', 'b', 'c', 'd'};
System.out.println(ch);		// abcd
  • char 배열을 println() 메서드로 출력할 시, 구분자(,)가 없이 그대로 출력된다

(2) 내림차순 정렬

Integer[] arr = {1, 26, 17, 25, 99, 44, 303};

Arrays.sort(arr, Collections.reverseOrder());

System.out.println("Sorted arr[] : " + Arrays.toString(arr));

/* 출력 결과
Sorted arr[] : [303, 99, 44, 26, 25, 17, 1] */
  • Arrays.sort()인자(arr) + 추가로 Collections.reverseOrder()를 전달
    • Comparator 객체 : Collections에서 기본으로 제공

(3) String 배열 오름차순 정렬

String[] arr = {"Apple", "Kiwi", "Orange", "Banana", "Watermelon", "Cherry"};

Arrays.sort(arr);

System.out.println("Sorted arr[] : " + Arrays.toString(arr));

/* 출력 결과
Sorted arr[] : [Apple, Banana, Cherry, Kiwi, Orange, Watermelon] */

('오름차순 정렬' 과 동일)

(4) String 배열 내림차순 정렬

String[] arr = {"Apple", "Kiwi", "Orange", "Banana", "Watermelon", "Cherry"};

Arrays.sort(arr, Collections.reverseOrder());

System.out.println("Sorted arr[] : " + Arrays.toString(arr));

/* 출력 결과
Sorted arr[] : [Watermelon, Orange, Kiwi, Cherry, Banana, Apple] */

('내림차순 정렬' 과 동일)

(5) String 배열을 문자열 길이 순서로 정렬

// 방법 1
String[] arr = {"Apple", "Kiwi", "Orange", "Banana", "Watermelon", "Cherry"};

Arrays.sort(arr, new Comparator<String>()) {
    @Override
    public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }
});

System.out.println("Sorted arr[] : " + Arrays.toString(arr));

// 방법 2 : Lambda식을 이용할 경우
String[] arr = {"Apple", "Kiwi", "Orange", "Banana", "Watermelon", "Cherry"};

Arrays.sort(arr, (s1, s2) -> s1.length() - s2.length());

System.out.println("Sorted arr[] : " + Arrays.toString(arr));

/* 출력 결과
Sorted arr[] : [Kiwi, Apple, Orange, Banana, Cherry, Watermelon] */
  • (1 ~ 5 의 정렬과는 달리) 이 경우에는 직접 Comparator를 구현해야 한다.

(6) int 배열의 일부분만 정렬

int[] arr = {1, 26, 17, 25, 99, 44, 303};

Arrays.sort(arr, 0, 4);		// index 0에서 index 4를 포함하는 배열만 정렬해라.

System.out.println("Sorted arr[] : " + Arrays.toString(arr));

/* 출력 결과
Sorted arr[] : [1, 17, 25, 26, 99, 44, 303] */
  • Arrays.sort(인자, 처음 index, 마지막 index) : 정렬할 범위를 지정

(7) 객체 배열 정렬

Fruit 클래스

// Comparable<Fruit> 를 구현
public static class Fruit implements Comparable<Fruit> {
    private String name;
    private int price;
    public Fruit(String name, int price) {
        this.name = name;
        this.price = price;
    }

    @Override
    public String toString() {
        return "{name: " + name + ", price: " + price + "}";
    }

    @Override
    public int compareTo(@NotNull Fruit fruit) {
        return this.price - fruit.price;
    }
}

Fruit 배열을 정렬

Fruit[] arr = {
        new Fruit("Apple", 100),
        new Fruit("Kiwi", 500),
        new Fruit("Orange", 200),
        new Fruit("Banana", 50),
        new Fruit("Watermelon", 880),
        new Fruit("Cherry", 10)
};

Arrays.sort(arr);

System.out.println("Sorted arr[] : " + Arrays.toString(arr));

/* 출력 결과
Sorted arr[] : [{name: Cherry, price: 10}, {name: Banana, price: 50}, {name: Apple, price: 100}, {name: Orange, price: 200}, {name: Kiwi, price: 500}, {name: Watermelon, price: 880}]
*/
  • 이 경우에는 클래스에 Comparable을 구현하여 비교해야 한다.

  • 자기 자신의 클래스와 인자로 전달되는 Fruit의 price 를 비교

8) 배열 복사 (배열 자르기)

배열의 전체/일부를 복사해서 새로운 배열을 만들어내는 메서드다.

결과적으로보면,
기존 배열에서 원하는 만큼의 새로운 배열을 만들어내기 때문에 배열 자르기로 분류했다.

(1) Arrays.copyOf()

import java.util.Arrays;

public class ArraySplit {
	public static void main(String[] args) {
    
    	int[] arr = {0, 1, 2, 3, 4, 5};
    
    	int[] arr1 = Arrays.copyOf(arr, 3);
        
        System.out.println(Arrays.toString(arr1));
	}
}

/* 출력 결과
0, 1, 2 */
  • Arrays.copyOf(원본 배열, 복사할 배열 길이);

    • 복사할 배열 길이

      • '배열의 크기'를 말함
      • '3'은 배열 크기가 3 이지, 3번째 인덱스를 뜻하는 게 X
        (만약 3번째 인덱스라고 할 경우는 0, 1, 2, 3 까지 나오게 됨)
    • 범위가 넘어가는 복사는 초기화값이 들어간다.

    • 배열 전체 복사, 새 배열로 반환

(2) Arrays.copyOfRange()

import java.util.Arrays;

public class ArraySplit {
	public static void main(String[] args) {
    
    	int[] arr = {0, 1, 2, 3, 4, 5};
    
    	int[] arr1 = Arrays.copyOfRange(arr, 0, 3);
        int[] arr2 = Arrays.copyOfRange(arr, position, arr.length);
        
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));
	}
}

/* 출력 결과
0, 1, 2
3, 4, 5 */
  • Arrays.copyOfRange(원본 배열, 시작 인덱스, 끝 인덱스);

    • 끝 인덱스는 포함하지 않는다.
      끝 인덱스를 포합하고 싶다면, '끝 인덱스 + 1' 이 필요

    • 범위가 넘어가는 복사는 초기화값이 들어간다.

    • 배열 일부 복사, 새 배열로 반환

9) 배열 검색

int[] arr = (3, 2, 0, 1, 4};

Arrays.sort(arr);
int idx = Arrays.binarySearch(arr, 2);
  • binarySearch(이진 검색 할 배열, 찾는 값)
    • 이진 검색
      • 배열의 검색할 범위를 반복적으로 절반씩 줄여가면서 검색 (반대는 '순차 검색')
      • 검색 속도가 빠름
      • 단, 배열이 정렬돼 있는 경우에만 사용 가능

10) 변환

// 방법 1
List list = Arrays.asList(new Integer[]{1, 2, 3, 4, 5});

// 방법 2
List list = Arrays.asList(1, 2, 3, 4, 5);
  • 배열을 List 에 담아서 반환

  • 배열 생성 없이, 저장할 요소들만 나열해도 된다

  • asList() 는 반환된 크기를 변경할 수 없으나, 다음 방법으로 사용한다면 크기를 변경할 수 있게 된다

List list = new ArrayList(Arrays.asList(1, 2, 3, 4, 5));
list.add(6);		// 크기를 변경할 수 있으므로, 예외 발생 X

11) 2차원 배열

(1) 정의

테이블 형태의 데이터를 저장하기 위한 배열

(2) 사용법

  1. 선언 및 생성

    int[][] score = new int[4][3];

    • score[0][0] = 88;
      • 배열 score 의 1행 1열에 88을 저장
  2. 초기화

    // 방법 1
    int[][] score = new int[][]{{}, {}, {}, {}};
    
    // 방법 2
    int[][] score = {{}, {}, {}, {}};
    
    // 예시 1 :  배열 원소마다 각기다른 크기로 지정 가능
    int[][] array = new int[3][];
    array[0] = new int[2];
    array[1] = new int[4];
    array[2] = new int[1];	
    
    // 예시 2 : 중괄호 초기화 할 때도 원소 배열들의 크기를 각기 다르게 생성 가능
    int[][] array2 = {
                        {10, 20},
                        {10, 20, 30, 40},
                        {10}
    					   };
    
    // 예시 3 : (1) 정의에서의 그림처럼 테이블에 데이터를 저정할 경우
    int[][] score = {
                      {88, 35, 100},
                      {84, 60, 55},
                      {100, 99, 72},
                      {33, 54, 77}
      			  };
  3. 출력 : toString()

    int[] arr = {1, 2, 3, 4, 5}
    
    System.out.println(Arrays.toString(arr))
    • 일차원 배열에만 사용 가능
      [0, 1, 2, 3, 4]
    • 2차원 배열(int[][] arr 처럼, 테이블 형태의 데이터를 저장하기 위한 배열)을 출력할 경우
      값이 출력되지 않고 각 객체의 주소가 나오게 된다.
  4. 출력 : deepToString()

    int[] arr = {(1, 2), (3, 4)}
    
    System.out.println(Arrays.deepToString(arr))
    • 다차원 배열 사용
      [[11, 12], [21, 22]]

    • 2차원 배열 or 다차원 배열 출력 시에 사용

3) 예시

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        String[][] words = {
                {"chair", "의자"},         // words[0][0], words[0][1]
                {"computer", "컴퓨터"},    // words[1][0], words[1][1]
                {"integer", "정수"}        // words[2][0], words[2][1]
        };

        Scanner sc = new Scanner(System.in);

        for (int i = 0; i < words.length; i++) {
            System.out.println("Q" + i + "." + words[i][0] + "의 뜻은?");

            String tmp = sc.nextLine();

            if (tmp.equals(words[i][1])) {
                System.out.println("정답입니다.");
            } else {
                System.out.println("틀렸습니다. 정답은 " + words[i][1] + "입니다.");
            }
            System.out.println();
        }
    }
}

/* 입력 및 출력 결과
Q0.chair의 뜻은?
dfd
틀렸습니다. 정답은 의자입니다.

Q1.computer의 뜻은?
컴퓨터
정답입니다.

Q2.integer의 뜻은?
정수
정답입니다.

*/

12) 3차원 배열

int[][][] MultiArray = {{{1, 2}, {3, 4}}, {{5, 6}, {7, 8}}};

ArrayList

참고: 자바 컬렉션 (Java Collection, 컬렉션 프레임워크)

1. 정의

  • List 인터페이스를 상속받은 클래스ㅍ

  • 크기가 가변적으로 변하는 선형 리스트

    선형 리스트 Linear List (순차 리스트 Ordered List) (자료 구조 中)

    • 데이터를 일정한 순서로 나열한 구조
    • 입력 순서대로 저장하는 데이터에 적합
    • 일반적으로 '배열' 을 이용하여 선형 리스트를 구현
    • 예시 : 가장 많이 연락이 온 순서 = ['다현', '정연', '쯔위', '사나', '지효']
  • 컬렉션에서 개체를 추가/삭제하면, ArrayList의 크기가 자동 조정된다.

    1. ArrayList에 객체를 생성하면, 내부에 10개의 객체를 저장할 수 있는 '초기 용량'을 가지게 된다

    2. ArrayList에 객체를 추가하면, 0번 인덱스부터 차례대로 저장

    3. ArrayList의 특정 인덱스의 객체를 제거하면, 바로 뒤 인덱스 ~ 마지막 인덱스까지 모두 1씩 당겨진다.

    4. ArrayList의 특정 인덱스의 객체를 삽입하면, 바로 뒤 인덱스 ~ 마지막 인덱스까지 모두 1씩 밀려난다.

    5. 순차적으로 배열에 저장하다가 배열에 더이상 공간이 없을 경우, 더 큰 배열을 생성하고 기존 배열 내용을 새로운 배열로 복사한 후 저장한다.

  • 각 데이터에 대한 인덱스를 가지고 있어, 조회 기능에 성능이 뛰어남

2. 배열 VS ArrayList

공통점

  • 선형 리스트 (순차 리스트)

  • 인덱스로 내부의 객체를 관리

차이점

  • 일반적인 배열 : 한번 생성되면 크기 변화 X

  • ArrayList

    • 객체들이 추가되어 저장 용량(capacity)을 초과 시, 부족한 크기만큼 저장 용량이 자동 증가
    • 객체 저장 시, 자동으로 인덱스가 부여됨
    • 최초 길이를 몰라도 생성 가능 (동적 배열 (즉, 크기가 가변적))

3. 사용법

class GFG {
    public static void main(String[] args) {

        // ArrayList 선언
        ArrayList<Integer> al = new ArrayList<Integer>();
  
        // ArrayList에 데이터 입력
        for (int i = 1; i <= 5; i++)
            al.add(i);
  
        // 결과 출력
        System.out.println(al);
  
        // 3번 데이터 제거
        al.remove(3);
  
        // 결과 출력
        System.out.println(al);
  
        // 하나씩 가져와서 결과 출력
        for (int i = 0; i < al.size(); i++)
            System.out.print(al.get(i) + " ");
    }
}

/* 출력 결과
[1, 2, 3, 4, 5]
[1, 2, 3, 5]
1 2 3 5 */

(1) 선언

// 타입 미설정 → Object 로 선언된다.
List list = new ArrayList();

// 타입설정 → Student객체만 사용 가능
List<Student> members = new ArrayList<Student>();
List<Student> members = new ArrayList<>();		// new 연산자 일 경우, 타입 파라미터 생략 가능
  • ArrayList에서는 제네릭< > 으로 타입을 명시해줄 것을 권장

  • 타입을 설정하면, 해당 타입의 객체들만 add 가능

  • <타입> 에는 wrapper 클래스만 가능
    참고: wrapper 클래스 (래퍼 클래스)

(2) 값 추가

// 예시 1 : 초기 용량 지정
List<Integer> num3 = new ArrayList<Integer>(10);

// 예시 2 : 생성 시, 값 추가
List<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3));

// 예시 3
List<Integer> list = new ArrayList<Integer>();

list.add(3); 	// 값 추가
list.add(null); 	// null값도 add 가능
list.add(1,10); 	// 인덱스 0에 1을, 인덱스 1에 10을 삽입

// 예시 4
List<Student> members = new ArrayList<Student>();

Student student = new Student(name,age);
members.add(student);
members.add(new Student("홍길동",15));  
  • 값 추가 방법 : ArrayList 의 add(index, value) 메소드 사용

  • index 를 생략한다면, ArrayList 맨 뒤에 데이터가 추가된다.

  • index 중간에 값을 추가한다면, 해당 인덱스부터 마지막 인덱스까지 모두 1씩(한 칸씩) 뒤로 밀려난다.

(3) 값 삭제

List<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3));

list.remove(1);  	// 인덱스 1 을 제거 (즉, 값 2 를 제거)

list.clear();  		// 모든 값을 제거
  • 값 추가 방법 : ArrayList 의 remove(index) 메소드 사용

  • 특정 인덱스의 객체를 제거하면, 바로 뒤 인덱스부터 마지막 인덱스까지 모두 앞으로 1씩(한 칸씩) 당겨진다.

(4) 값 수정

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

list.add(99);
list.add(15);
list.add(3);

list.set(1, 10);		// 15 -> 10 으로 수정된다.
  • list.set(수정할 인덱스, 수정할 값);

(5) 크기 구하기

List<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3));

System.out.println(list.size()); 	// list 의 크기는 3 (인덱스가 값 1, 값 2, 값 3 으로 3 칸 있기 때문)
  • 크기 구하는 방법 : ArrayList 의 size() 메소드를 사용

(6) 값 검색

List<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3));

System.out.println(list.contains(1));
System.out.println(list.indexOf(1));
  • 방법 1 : ArrayList 의 contains(value) 메소드를 사용

    • 값이 있다면 → true
    • 값이 없다면 → false
  • 방법 2 : ArrayList 의 indexOf(value) 메소드를 사용

    • 값이 있다면 → 1
    • 값이 없다면 → -1

    indexOf()

    • .indexOf("찾을 특정 문자", "시작할 위치")
    • "시작할 위치" : 생략 가능 (생략할 경우, 0번째(처음부터) 찾기 시작)

    참고: String 클래스 - 예시 5 : indexOf() 문자열 찾기

(7) 값 출력

// 방법 1 : 0 번째 인덱스를 출력
List<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3));

System.out.println(list.get(0));
}		

// 방법 2 : for문으로 전체 인덱스를 출력     
List<Integer> list = new ArrayList<Integer>(Arrays.asList(1,2,3));

for(Integer i : list) { 		
    System.out.println(i);
}

// 방법 3 : Iterator
Iterator iter = list.iterator();		// Iterator 선언

while(iter.hasNext()) {		// 다음 값이 있는지 체크
    System.out.println(iter.next());		// 값 출력
}
  • 값 출력 방법 : ArrayList 의 get(index) 메소드를 사용
    → 원하는 인덱스의 값을 리턴 할 수 있다.

Iterator

  • Java 의 컬렉션 프레임워크에서 컬렉션에 저장되어 있는 요소들을 읽어오는 방법을 표준화한 것
  • 집합체로부터 정보를 얻어낸다
  • 어떤 컬랙션이라도 동일한 방식으로 접근이 가능하여, 그 안에 있는 항목들에 접근할 수 있는 방법을 제공
  • 메소드
    • hasNext() : 읽어올 요소가 남아있는지 확인하는 메서드, 요소가 있으면 true, 없으면 false
    • next() : 다음 데이터를 반환
    • remove() : next()로 읽어온 요소를 삭제

컬렉션 프레임워크

  • 데이터를 저장하는 구조에 따라 3가지 인터페이스로 구성 (Set, List, Map)
  • 컬렉션 프레임워크 : 데이터를 저장하는 클래스들을 표준화한 설계
  • Set, List, Map : 어떤 데이터들의 집합체

(8) 뒤집기

Collections.reverse()

(9) 비교

Arrays.equals(배열1, 배열2)
  • 배열1 == 배열2 인지 비교한다.

4. 장단점

장점

  • 다음 경우에는 작업 시간 Short

    • 배열에 객체를 '순차적으로 저장'할 경우

    • '마지막에 저장된 객체부터' 삭제할 경우

단점

  • 다음 경우에는 작업 시간 Long

    • '배열의 중간에' 객체를 추가할 경우

    • '배열의 중간에 있는 객체'를 삭제할 경우

      (다른 데이터의 위치를 이동시켜줘야 하기 때문에, 다뤄야할 데이터 개수 多수록, 작업시간 Long)

삭제가 이루어지는 과정
1. 삭제할 객체의 바로 아래의 데이터를 복사

  1. 복사한 데이터(아래)를 삭제할 객체(위)로 덮음
  1. 만약, 삭제할 객체가 마지막 데이터일 경우, 복사 없이 단순히 null로 변경

연습 문제

1. 총합, 평균

배열의 모든 요소를 더해서 총합과 평균을 구하라

class Arrays3_2 {
    public static void main(String[] args) {
        int sum = 0; // 총합을 저장
        float avg = 0f; // 평균을 저장

        int[] score = {100, 40, 33, 50, 77, 29};

        for (int i = 0; i < score.length; i++) {
            System.out.println("score[" + i + "] = " + score[i]);
            sum += score[i];
        }

        avg = sum / (float) (score.length); // 계산결과를 float 타입으로 얻기 위해 형변환

        System.out.println("총합 = " + sum);
        System.out.println("평균 = " + avg);
    }
}

2. 최대값, 최소값

배열의 요소 중에서 가장 큰 값과 가장 작은 값을 찾아라

class Arrays3_3 {
    public static void main(String[] args) {
        int[] score = {65, 97, 88, 43, 33, 91, 28};

        int max = score[0]; // 최대값을 배열의 첫 번째 값으로 초기화 한다.
        int min = score[0]; // 최소값을 배열의 첫 번째 값으로 초기화 한다.

        for (int i = 0; i < score.length; i++) {
            if (score[i] > max) {
                max = score[i];
            } else if (score[i] < min) {
                min = score[i];
            }
        }

        System.out.println("최대값 = " + max);
        System.out.println("최소값 = " + min);
    }
}
  • score 를 돌면서 score[i]에 값이 할당되는데,
    score[i] 이 max 보다 크면, max 를 score[i]로 바꿔끼운다.

3. 랜덤으로 숫자 섞기

class Arrays3_4 {
    public static void main(String[] args) {
        int[] numArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        System.out.println("원본 = " + Arrays.toString(numArr));

        for (int i = 0; i < numArr.length; i++) {
            int num = (int) (Math.random() * 10); // 0 ~ 9 의 랜덤 수

            int tmp = numArr[0]; // 배열의 첫 번째 수로 계속 초기화 된다.

            // 랜덤한 위치의 값과 배열의 첫 번째 수가 서로 바뀐다.
            numArr[0] = numArr[num];
            numArr[num] = tmp;

            System.out.println(i + 1 + " 번째 변경 : " + Arrays.toString(numArr));
        }

        System.out.println("결과 = " + Arrays.toString(numArr));
    }
}

참고: [Java] 자바 ArrayList 사용법 & 예제 총정리
참고: [Java] 래퍼 클래스(Wrapper Class)란 무엇인가? (박싱, 언박싱)
참고: [Java]이터레이터(Iterator) 란?
참고: Java - 배열 정렬(Sorting) (오름차순, 내림차순)
참고: Arrays.copyOf, Arrays.copyOfRange 배열 복사
참고: [Java] 특정 인덱스에서 배열 자르기

profile
개발자로 거듭나기!

0개의 댓글