[Java/자바] 배열과 ArrayList
들어가기 전에
본 글은 제가 참여하고 있는 자바 기초 스터디에서 제가 발표한 내용으로 위의 책 Chapter 07 배열과 ArrayList 파트를 정리한 글입니다.
배열이란?
연관된 데이터를 하나의 변수에 담을 수 있는 자료구조
자료형이 같은 여러 데이터를 한번에 관리할 수 있는 자료형
int num1 = 1;
int num2 = 2;
int num3 = 3;
...
int num10 = 10;
int[] array = new int[] {1, 2, 3, ... 10};
자료구조(Data Structure)란?
원소들이 논리적으로 정의된 규칙에 의해 나열되며 자료에 대한 처리를 효율적으로 수행할 수 있도록 자료를 구분하여 표현한 것이라고 합니다.
자료를 더 효율적으로 저장 및 관리하기 위해 사용
자료구조를 사용하면 실행시간을 단축시켜주거나 메모리 절약 등의 효과를 볼 수 있음
배열의 장단점
장점
- 구현이 쉽다.
- 검색 성능이 좋다.
인덱스(index)를 이용한 무작위 접근이 가능하므로 검색에서 빠른 성능을 기대할 수 있다. - 연속된 메모리 공간에 할당하기 때문에 연결 리스트(Linked List)보다 빠른 성능을 보인다.
- 참조를 위한 추가적인 메모리 할당이 필요 없다.
단점
- 크기를 변경할 수 없다.
배열은 생성할 때 지정한 크기를 바꿀 수 없기 때문에 너무 크게 설정하면 메모리가 낭비되고 너무 작게 설정하면 그 이상의 자료를 저장할 수 없음 - 메모리 재사용이 불가능하다.(메모리 낭비)
배열은 설정된 사이즈 만큼의 메모리를 할당받아 사용하기 때문에 데이터의 존재 유무와 관계없이 일정한 크기의 메모리를 점유하고 있습니다. 즉 배열 요소를 삭제하더라도 해당 메모리를 재사용할 수 없습니다. - 배열 중간에 데이터를 삽입하거나 삭제할때 비효율적이다.
배열 사용방법
선언 및 초기화
배열을 선언하면 선언한 자료형과 배열 길이에 따라 메모리가 할당
자바에서 배열을 선언하면 그와 동시에 각 요소의 값이 초기화
정수: 0
실수: 0.0
객체 배열: null
// 선언
자료형[] 배열이름 = new 자료형[개수]; // 주로 이방법으로 사용
자료형 배열이름[] = new 자료형[개수];
// 선언과 동시에 초기화
자료형[] 배열이름 = new 자료형[] {1, 2, 3};
자료형[] 배열이름 = {1, 2, 3};
// 배열 자료형 선언 후 초기화
int[] array;
array = new int[] {1, 2, 3, 4, 5}; // new int[] 생략 불가
// int요소가 10개인 배열 선언 및 사용
int[] array = new int[10];
array[0] = 1; // 0번째(첫번째) 요소에 1 저장
array[1] = 2; // 1번째(두번째) 요소에 2 저장
/*
* array 출력시 0, 1번째를 제외한 2~9번째는 기본값인 0출력
* 1
* 2
* 0
* 0
* ...
* 0
*/
배열 복사
이미 존재하는 배열을 자료형 및 배열 크기가 같은 배열을 새로 만들거나 더 큰 배열을 만들어 기존 배열에 저장된 자료를 가져오려 할 때 배열 복사를 사용
System.arraycopy(src, srcPos, dest, destPos, length);
/*
* src: 복사할 배열
* srcPos: 복사할 첫 위치
* dest: 대상 배열
* destPos: 붙여 넣을 첫 위치
* length: 복사할 요소 개수
*/
// 10개의 공간을 가진 배열을 선언하고 5번째부터 5개의 요소를 복사
int[] array = new int[] {1, 2, 3, 4, 5};
int[] array2 = new int[10];
int[] array3 = array.clone();
int[] array4 = Arrays.copyOf(array, array.length);
int[] array5 = Arrays.copyOfRange(array, 0, 5);
System.arraycopy(array, 0, array2, 5, 5);
for (int i : array2) {
System.out.println(i);
}
/*
* array2 출력시 0~4번째는 기본값인 0출력
* 0
* 0
* 0
* 0
* 0
* 1
* 2
* 3
* 4
* 5
*/
객체 배열 복사
객체 배열의 경우 배열 안에 인스턴스 자체가 아닌 인스턴스의 주소값을 가리키고 있기 때문에 원본 배열의 값을 변경하면 복사된 배열의 값도 변경
- 얕은 복사
Book[] bookArray1 = new Book[3];
bookArray1[0] = new Book("객체지향의 사실과 오해", "조영호");
bookArray1[1] = new Book("자바 ORM 표준 JPA 프로그래밍", "김영한");
bookArray1[2] = new Book("Two Scoops of Django", "대니얼 로이 그린펠드");
for(Book book : bookArray1) {
System.out.println(book);
}
bookArray1[0].setName("name");
bookArray1[0].setAuthor("author");
Book[] bookArray2 = bookArray1.clone();
Book[] bookArray3 = Arrays.copyOf(bookArray1, bookArray1.length);
Book[] bookArray4 = Arrays.copyOfRange(bookArray1, 0, 3);
/*
* bookArray2, bookArray3, bookArray4 출력시 아래와 같이 0번째 요소가 test로 변경
* Book [name=test, author=test]
* Book [name=자바 ORM 표준 JPA 프로그래밍, author=김영한]
* Book [name=Two Scoops of Django, author=대니얼 로이 그린펠드]
*/
- 복사된 배열이나 원본 배열이 변경될 때 서로 간의 값이 같이 변경됩니다.
- 깊은 복사
Book[] bookArray1 = new Book[3];
bookArray1[0] = new Book("객체지향의 사실과 오해", "조영호");
bookArray1[1] = new Book("자바 ORM 표준 JPA 프로그래밍", "김영한");
bookArray1[2] = new Book("Two Scoops of Django", "대니얼 로이 그린펠드");
for(Book book : bookArray1) {
System.out.println(book);
}
Book[] bookArray2 = new Book[3];
for(int i=0;i<bookArray1.length;i++) {
bookArray2[i] = new Book(); // 비어있는 인스턴스 생성
bookArray2[i].setName(bookArray1[i].getName());
bookArray2[i].setAuthor(bookArray1[i].getAuthor());
}
bookArray1[0].setName("name");
bookArray1[0].setAuthor("author");
for(Book book : bookArray2) {
System.out.println(book);
}
/*
* bookArray2 출력시 값 변경 없이 출력
* Book [name=객체지향의 사실과 오해, author=조영호]
* Book [name=자바 ORM 표준 JPA 프로그래밍, author=김영한]
* Book [name=Two Scoops of Django, author=대니얼 로이 그린펠드]
*/
- 복사된 배열이나 원본 배열이 변경될 때 서로 간의 값은 바뀌지 않습니다.
다차원 배열
다차원 배열은 평면이나 공간 개념을 구현하는 데 사용합니다.
이차원 배열
바둑, 체스, 네비게이션 지도 등을 구현할 때 사용
// 선언 및 초기화 방법은 일차원 배열과 동일하나 차원이 늘어날 수록 []가 추가됨
자료형[][] 배열이름 = new 자료형[행 개수][열 개수];
int[][] array = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
// 이차원 배열 출력
for (int i=0;i<array.length;i++) { // array.length 행 길이
for (int j=0;j<array[i].length;j++) { // array.length 열 길이
System.out.print(array[i][j] + "\t");
}
System.out.println();
}
ArrayList란?
기본 배열의 단점을 보완한 자료 구조
크기가 가변적으로 변함
내부적으로 저장이 가능한 메모리 용량(Capacity)이 있으며 현재 사용 중인 공간의 크기(Size)가 있음
현재 가용량(Capacity) 이상을 저장하려고 할 때 더 큰 메모리 공간을 새롭게 할당
ArrayList 사용방법
ArrayList<자료형> 배열 이름 = new ArrayList<자료형>();
ArrayList<Integer> array1 = new ArrayList<Integer>();
ArrayList<Integer> array2 = new ArrayList<>(10); // 초기 용량(Capacity) 설정
ArrayList<Integer> array4 = new ArrayList<>(array3); // 다른 Collection값으로 초기화
// ArrayList에 요소 추가
array1.add(1);
array1.add(2);
array1.add(3);
array1.add(4);
array1.add(5);
// ArrayList에 추가된 요소 개수 반환
array1.size(); // 5
// ArrayList의 index 위치에 있는 요소값 반환
array1.get(0); // 1
// ArrayList의 index위치에 있는 요소값 제거후 반환
array1.remove(4); // 5
// ArrayList가 비어있는지 확인
array1.isEmpty(); // false
// ArrayList 안에 값이 존재 하는지 확인
array1.contains("A"); // false
array1.indexOf("Hello") // -1
/*
* contains는 값이 존재하는 경우 true 없는경우 false 리턴
* indexOf는 값이 존재하는 경우 해당 인덱스값 없는경우 -1 리턴
* 두 메소드 모두 대소문자를 구분
*/