Array and ArrayList with Java

민준·2023년 2월 19일
0

1. Array

ㄱ) 배열

배열 은 물리적으로도 논리적으로도 연속되어있는, 프로그램에서 굉장히 많이 사용하는 자료구조입니다.
동일한 자료형의 변수를 한 번에 순차적으로 관리할 때 사용합니다.

ㄴ) 배열의 초기화

배열을 선언할 때에는 배열의 길이를 명시해야합니다. 이때 정수는 0, 실수는 0.0, 객체는 null로 초기화 됩니다.
반면 선언과 동시에 초기화 할 수 있는데 이때에는 배열의 개수를 명시하지 않습니다.

전자의 경우 따로 값을 초기화하지 않은 5~9 인덱스의 값이 0으로 초기화되었습니다.
후자의 경우 실제 초기화된 배열의 크기를 컴퓨터가 파악해 'numbersInit' 배열의 길이가 3으로 출력되었습니다.

같은 스테이트먼트에서 초기화할 때에는 아래처럼도 가능합니다.

int[] numbers = {1, 2, 3};

a) 문자의 배열

반복문의 초기화 부분에 문자로 초기화된 변수 또한 증가시키면 알파벳을 순서대로 배열에 초기화할 수 있습니다.
이런 문자의 배열을 자바에서 String 이라는 클래스로 제공하고 있습니다.

public class ArrayTest {

	public static void main(String[] args) {
		
		char[] alphabets = new char[26];
		char ch = 'A';
		
		for (int i = 0; i < alphabets.length; i++, ch++) {
			alphabets[i] = ch;
		}
		
		for (int i = 0; i < alphabets.length; i++, ch++) {
			System.out.println(alphabets[i]);
		}
	}
}

b) 객체의 배열

객체 배열 은 참조 자료형을 선언합니다. 각 요소를 'new'를 활용해 생성해서 저장해야하며
배열만 생성하는 경우 요소는 'null'로 초기화됩니다.

ㄷ) 배열의 길이

앞서 말한 것처럼 배열의 길이를 배열을 선언할 때에 명시하고 반복문을 수행할 때 그 자체의 길이를 회수로 수행하면
위의 이미지처럼 값이 초기화되지 않은 인덱스의 값까지 반복수행에 포함됩니다.
이 경우 아래와 같이 따로 변수를 초기화하여 카운트해 그 값을 회수로 설정하면 되겠습니다.

public class ArrayTest {

	public static void main(String[] args) {
		
		int[] numbers = new int[10];
👉		int size = 0;
		
		numbers[0] = 1; size++;
		numbers[1] = 2; size++;
		numbers[2] = 3; size++;
		numbers[3] = 4; size++;
		numbers[4] = 5; size++;
		
		for (int i = 0; i < size; i++) {
			System.out.println("numbers의 " + i + "번째 값 : " + numbers[i]);
		}
	}
}

ㄹ) 배열 복사하기

기존 배열과 같은 배열을 만들거나 배열이 꽉 찬 경우 더 큰 배열을 만들고 기존 배열 자료를 복사할 수 있습니다.

System.arraycopy(src, srcPos, dest, destPos, length)
매개변수설명
src복사할 배열 이름
srcPos복사할 배열의 첫 번째 위치
dest복사해서 붙여넣을 대상 배열의 이름
destPos복사해서 붙여넣은 대상 배열의 첫 번째 위치
lengthsrc에서 dest로 자료를 복사할 요소의 개수

a) 객체 배열 복사하기

얕은 복사 : 배열 요소의 주소만 복사되므로 배열 요소가 변경되면 복사된 배열의 값도 변경됩니다.
아래 코드를 실행해보면 'bookArray1[0]'의 값이 "나목", "박완서"로 변경되면서
👉 'bookArray2[0]'의 값 또한 똑같이 변경되었음을 알 수 있습니다.
이후 두 배열 요소의 주소값을 출력해보니 똑같습니다.

public class ObjectCopy {

	public static void main(String[] args) {
		Book[] bookArray1 = new Book[3];
		Book[] bookArray2 = new Book[3];
		
		bookArray1[0] = new Book("태백산맥1", "조정래");
		bookArray1[1] = new Book("태백산맥2", "조정래");
		bookArray1[2] = new Book("태백산맥3", "조정래");
		
        // 배열 복사 메서드
		System.arraycopy(bookArray1, 0, bookArray2, 0, 3);
		
		for (int i = 0; i < bookArray2.length; i++) {
			bookArray2[i].showBookInfo();
		}
		
		bookArray1[0].setBookName("나목");
		bookArray1[0].setAuthor("박완서");
		
👉		bookArray1[0].showBookInfo();
		bookArray2[0].showBookInfo();
		
		for (int i = 0; i < bookArray2.length; i++) {
			System.out.println(bookArray1[i]);
			System.out.println(bookArray2[i]);
		}
	}
}

깊은 복사 : 위처럼 '얕은 복사'는 복사한 데이터에 변경이 일어나면 기존 데이터도 동시에 변경되어 버리는 문제가 있습니다.
이때 다른 배열의 요쇼에 인스턴스를 각각 다시 생성하고 요소에 직접 복사할 값으로 초기화하면
'얕은 복사'와는 다르게 말 그대로의 '사본'이 생기게 됩니다.
👉 아래 코드를 실행해보면 맨 아래 두 for문의 결과가 다른 것을 확인할 수 있습니다.

public class ObjectCopy2 {

	public static void main(String[] args) {
		
        // Book 타입의 길이가 3인 배열 생성
		Book[] bookArr1 = new Book[3];
		Book[] bookArr2 = new Book[3];
		
        // bookArr1
		bookArr1[0] = new Book("태백산맥1", "조정래");
		bookArr1[1] = new Book("태백산맥2", "조정래");
		bookArr1[2] = new Book("태백산맥3", "조정래");
		
        // bookArr2, 인스턴스를 새로 생성
		bookArr2[0] = new Book();
		bookArr2[1] = new Book();
		bookArr2[2] = new Book();
		
        // bookArr1의 요소값들을 bookArr2에 초기화
		for (int i = 0; i < bookArr1.length; i++) {
			bookArr2[i].setBookName(bookArr1[i].getBookName());
			bookArr2[i].setAuthor(bookArr1[i].getAuthor());
		}
		
        // bookArr1[0] 값 변경
		bookArr1[0].setBookName("나목");
		bookArr1[0].setAuthor("박완서");
		
👉		for (int i = 0; i < bookArr1.length; i++) {
			bookArr1[i].showBookInfo();
		}
		
		for (int i = 0; i < bookArr2.length; i++) {
			bookArr2[i].showBookInfo();
		}
	}
}

ㅁ) 향상된 for 문 (enhanced for loop)

배열 요소의 처음부터 끝까지 모든 요소를 참조할 때 편리한 반복문입니다.
아래 코드를 예로 들면 'String s'라는 변수를 만들어 배열에서 하나씩 요소를 받아 출력한 것입니다.

String[] strArr = {"Java", "Android", "C"};
		
for (String s : strArr) {
	System.out.println(s);
}

아래 파이썬 코드와 다름이 없습니다.

arr = ['Java', 'Android', 'C']

for s in arr:
	print(s)

2. 다차원 배열

다차원 배열 이란 2차원 이상의 배열을 말합니다.
'pandas', 'numpy'를 배운 저에겐 어렵지 않은 챕터이지 않을까 희망하며 시작을 해보겠습니다.

// 2행 3열 형태의 2차원 배열
int[][] arr = new int[2][3];

이런 2차원 배열을 순회하는 반복문은 이중 for문을 이용할 수 있습니다.
일반적으로 바깥의 for문은 행, 안쪽의 for문은 열 인덱스라고 생각하면 되겠습니다.

public class TwoDimensionArr {

	public static void main(String[] args) {
		
		int[][] arr = new int[2][3];		// 배열 크기 명시
		int[][] arr1 = {{1,2,3}, {4,5,6}};  // 배열 직접 초기화
		
		System.out.println(arr.length);	  	// 'arr'의 길이 2
		System.out.println(arr[0].length);  // 'arr[0](행)'의 길이 3
		System.out.println(arr[1].length);  // 'arr[1](열)'의 길이 3
		
		for (int i = 0; i < arr1.length; i++) {
			for (int j = 0; j < arr1[i].length; j++) {
				System.out.println(arr1[i][j]);
			}
		}
	}
}

3. ArrayList

ArrayList 는 Java 'JDK'에서 제공하는, 객체 배열의 기능을 구현한 클래스입니다.
기존 배열은 길이를 정해 선언하므로 사용 중 크기가 부족하면 다른 배열로 복사하거나
중간 요소가 삭제되거나 삽입되는 경우도 나머지 요소에 대해 조정하는 코드를 직접 구현해야 하는데
'ArrayList' 클래스는 여러 메서드와 속성 등을 사용하여 객체 배열을 편리하게 관리할 수 있습니다.

ArrayList 클래스 주요 메서드

메서드설명
boolean add(E e)요소 하나를 배열에 추가. (E : 요소의 자료형)
int size()배열에 추가된 요소 전체 개수 반환
E get(int index)배열의 index 위치에 있는 요소 값 반환
E remove(int index)배열의 index 위치에 있는 요소 값 제거하고 그 값을 반환
boolean isEmpty()배열이 비어있는지 확인

다만 'ArrayList'에서는 인덱스를 제공하지 않기 때문에 위의 'E get()'메서드를 사용하면 되겠습니다.

import java.util.ArrayList;

public class ArrayListTest {

	public static void main(String[] args) {
		
		ArrayList<String> list = new ArrayList<String>();
		list.add("aaa");
		list.add("bbb");
		list.add("ccc");

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

'ArrayList'를 선언할 때 자료형을 명시하지 않을 수는 있는데 이때 값을 반환받기 위해서는 캐스팅이 필요합니다.

for (int i = 0; i < list.size(); i++) {
	String s = (String)list.get(i);
}    

배열 응용 프로그램 p.226


profile
백엔드 포지션 공부 중입니다.

0개의 댓글