안녕하세요😎 백엔드 개발자 제임스입니다 :)
오늘은 프로그래밍의 기초 개념인 배열에 관해서 포스팅하려고 합니다. 포스팅하기 전에! 이번 포스팅은 배열의 기본적인 개념을 알고 있다는 가정하에 정리했음을 미리 알립니다.
따라서 이번 주제는 [배열 다루기] 입니다! :)
배열을 다루는 방법은 굉장히 많은데요. 그중에서 Arrays와 System.arraycopy에 대해서 설명하겠습니다. 여기서 배열을 다룬다는 의미는 배열을 복사하거나 추가, 삭제 등 다양한 기능을 의미합니다. 이제 자세하게 설명을 하도록 하겠습니다.
1. System.arraycopy()
- arrayclass는 이름 그대로 배열을 복사하는, System 클래스의 메서드입니다.
- 해당 메서드는 반환을 하지 않는 void입니다.
void arraycopy(Object src, int srcPos, Object dst, int dstPos, int length)
* src : 원본 배열
* srcPos : 원본 배열에서 복사할 항목의 시작 인덱스
* dest : 새 배열
* destPos : 새 배열에서 붙여 넣을 시작 인덱스
* length : 복사할 개수
사용 예시
int[] srcArr = {1,2,3,4,5};
int[] destArr = {0, 0, 0, 0, 0};
System.arraycopy(srcArr, 0, destArr, 0, 5);
System.out.println(Arrays.toString(destArr));
위 코드에서 출력시 사용된 Arrays.toString 에 대해서는 아래에서 다룹니다.
위 코드를 예시로 설명하겠습니다. 먼저 결론부터 말하자면, 마지막 출력 구문에서 {1, 2, 3, 4, 5}로 srcArr 내용과 똑같이 출력됩니다. 여기서 알 수 있는 것은 srcArr의 내용이 destArr에 그대로 복사되었다는 것입니다.
즉, 'arraycopy 메소드를 통해서 srcArr의 인덱스 0번부터 길이 5만큼 해당하는 내용들을 destArr의 배열 0번부터 해당하는 위치 저장한다'라고 이해할 수 있습니다. 따라서 src의 인덱스 0번의 1부터 길이 5에 해당하는 정수 5가 destArr에 인덱스 0번부터 차례로 복사된 것이죠.
아래부터 다양한 방법으로 사용해보겠습니다.
#2 arraycopy안에 입력값 변경
int[] srcArr = {1,2,3,4,5};
int[] destArr = new int[6]; // {0, 0, 0, 0, 0, 0}
System.arraycopy(srcArr, 2 , destArr, 0, 3);
System.out.println(Arrays.toString(destArr));
이번에는 destArr을 크기가 6만큼 배열을 생성했습니다.
그리고 arraycopy의 인자로 (srcArr, 2, destArr, 0, 3)가 입력되었습니다. destArr은 어떠한 결과가 출력될까요?
- srcArr의 인덱스 2번부터 길이 3만큼에 배열 -> {3, 4, 5}
- destArr의 0번 부터 저장
따라서 결과는 [3, 4, 5, 0, 0, 0] 의 형태로 출력될 것입니다.
#3 destArr 크기 변경
int[] srcArr = {1,2,3,4,5};
int[] destArr = new int[3];
System.arraycopy(srcArr, 2 , destArr, 0,3);
System.out.println(Arrays.toString(destArr));
이번에는 destArr의 배열 크기를 3으로 줄여보았습니다. 결과는 destArr에 [3, 4, 5] 가 복사되어 출력됩니다.
#4 배열 중간에 복사하기
int[] srcArr = {1,2,3,4,5};
int[] destArr = new int[6];
System.arraycopy(srcArr, 0 , destArr, 2,4);
System.out.println(Arrays.toString(destArr));
이번에는 destArr의 복사받을 시작 위치를 인덱스 2로 했습니다. 그리고 srcArr의 인덱스 0번부터 길이 4만큼 복사를 합니다. 결과는 어떨까요?
destArr은 [0, 0, 1, 2, 3, 4] 가 됩니다.
#5 오류 발생
- arraycopy의 입력된 값에서 length(복사할 길이)가 srcArr의 크기보다 크다면 ArrayIndexOutOfBoundsException이 발생합니다.
- 복사 받을복사받을 배열의 크기가 복사받을 내용보다 작다면 동일한 에러가 발생합니다.
이처럼 크기와 관련해서 오류가 많이 발생하니 배열의 크기를 신경 쓰면서 사용하는 게 좋겠습니다.
추가로 위에서 알 수 있듯이 기존의 배열 내용이 있어도, 복사를 받으면 덮어쓰기가 됩니다.
2. Arrays 클래스
- 배열 복사, 항목 정렬, 항목 검색, 항목 비교를 위해 사용되는 클래스입니다.
- Java.util 패키지에서 구현된 클래스입니다.
- static 이므로 Arrays 클래스로 바로 사용 가능합니다.
Arrays는 배열을 쉽게 다룰 수 있도록 도와주는 도구와 같습니다. 이러한 도구를 잘 활용하기 위해서는 메서드들을 알고 있으면 좋습니다.
Arrays의 다양한 메서드
1) String toString(배열)
"[값1, 값2 ,,, ] " 와 같은 문자열 리턴
- 배열 내의 값들을 일괄로 출력할 때 주로 사용합니다.
- 단순히 System.out.println(arr); 사용할 시에는 주소값이 출력됩니다.
int[] arr = new int[]{1,5,2,4,8};
System.out.println(arr); // [I@3ac3fd8b
System.out.println(Arrays.toString(arr)); // [1, 5, 2, 4, 8]
2) void sort(배열)
배열 전체 항목을 오름차순으로 정렬
- 타입이 void이기 때문에 새로운 변수, 주소값으로 받을 필요가 없습니다.
- 아래와 같이 사용한 후 arr을 출력하면 정렬된 모습을 알 수 있습니다.
- 오름차순 -> 1, 2, 3, 4,..
int[] arr = new int[]{1,5,2,4,8};
Arrays.sort(arr); // arr 배열 내부를 정렬시킴.
System.out.println(Arrays.toString(arr)); // [1, 2, 4, 5, 8]
3) copyOf(원본 배열, 복사할 길이)
원본 배열의 0번 인덱스에서 복사할 길이 만큼 복사한 배열 리턴
- 복사할 길이는 원본 배열보다 커도 됩니다.
- 이는 리턴되는 배열의 길이가 됩니다.
int[] arr = new int[]{1,5,2,4,8};
int[] copyArr = Arrays.copyOf(arr,5);
System.out.println(Arrays.toString(copyArr)); // [1, 5, 2, 4, 8]
현재 코드에서 arr 배열에서 길이 5만큼 복사한다고 지정해준 모습입니다. 보다시피 arr은 길이가 5이기 때문에 copyArr 또한 arr과 동일하게 값을 같습니다.
(*) 아래 코드가 중요한 포인트입니다.
int[] arr = new int[]{1,5,2,4,8};
int[] copyArr = Arrays.copyOf(arr,6);
System.out.println(Arrays.toString(copyArr)); // [1, 5, 2, 4, 8, 0]
해당 코드에서 copyOf의 인자를 보면, 복사할 길이가 6으로 arr의 길이보다 큰 것을 알 수 있습니다. 과연 결과는 어떻게 될까요?
copyOf는 복사할 길이가 원본 배열보다 크다고 해서 에러가 발생하지 않습니다. 대신 새로 생성된 배열에 빈 공간이 형성됩니다. 위 코드에 적힌 주석이 출력된 결과입니다. 이것을 다르게 생각해보면, copyOf 안에 적힌 length는 새로운 배열의 길이와 동일한 것을 알 수 있습니다.
4) copyOfRange(원본 배열, 시작 인덱스, 끝 인덱스)
원본 배열의 시작 인덱스에서 끝 인덱스 전까지 복사한 배열 리턴
- copyOf() 메서는 원본 배열의 0번 인덱스부터 복사했다면, 해당 메서드는 범위를 지정하여 복사합니다.
int[] arr = new int[]{1,5,2,4,8};
int[] copyArr = Arrays.copyOfRange(arr,1,3);
System.out.println(Arrays.toString(copyArr)); // [5, 2]
보다시피 arr의 1번 인덱스부터 3번 인덱스 전(2번 인덱스)까지 복사한 것을 알 수 있습니다.
copyOfRange() 메서드도 끝 인덱스를 원본 배열보다 크게해도 에러가 발생하지 않습니다. 오히려 공간이 생기게 됩니다.
아래 코드가 그 예시입니다.
int[] arr = new int[]{1,5,2,4,8};
int[] copyArr = Arrays.copyOfRange(arr,2,6);
System.out.println(Arrays.toString(copyArr)); // [2, 4, 8, 0]
5) boolean equals(배열, 배열)
두 배결 비교 ( 단, 중첩 배열의 항목은 비교하지 않음, 배열의 1차 항목 값만 비교)
#1
int[] arr = new int[]{1,5,2,4,8};
int[] arr2 = new int[]{1,5,2,4,8};
boolean equal = Arrays.equals(arr, arr2);
System.out.println(equal); //true
#2
int[] arr = new int[]{1,5,2,4,8};
int[] arr2 = new int[]{1,5,2,4,9};
boolean equal = Arrays.equals(arr, arr2);
System.out.println(equal); //false
6) void fill(배열, 값) / void fill(배열, 시작 인덱스, 끝 인덱스, 값)
전체 배열 항목에 입력한 값으로 저장
or (배열, 시작 인덱스, 끝 인덱스, 값) : 시작 인덱스부터 끝 인덱스까지의 항목에만 입력한 값으로 저장
#1 fill(배열, 값)
int[] arr = new int[]{1,5,2,4,8};
Arrays.fill(arr,7);
System.out.println(Arrays.toString(arr)); // [7, 7, 7, 7, 7]
#2 fill(배열, 시작 인덱스, 끝 인덱스, 값)
int[] arr = new int[]{1,5,2,4,8};
Arrays.fill(arr,1,4,7);
System.out.println(Arrays.toString(arr)); // [1, 7, 7, 7, 8]
'개발 > Java' 카테고리의 다른 글
[JAVA 파헤치기] 필드(Field)와 메서드(Method) 쉽게 이해하기 2 - 메서드 (6) | 2022.05.16 |
---|---|
[JAVA 파헤치기] 필드(Field)와 메서드(Method) 쉽게 이해하기 1 - 필드 (10) | 2022.05.15 |
[JAVA 파헤치기] 문자 타입 'char' 와 문자열 'String' 의 진실 (18) | 2022.05.06 |
[JAVA 파헤치기] 객체 지향, 클래스, 객체 개념 다루기 (5) | 2022.03.07 |
Thread (0) | 2021.05.14 |