본문 바로가기
Java의 정석/컬렉션 프레임워크

Arrays 클래스

by Hwanii_ 2023. 9. 20.
728x90

ch11 - 25 ~ 29 Arrays 클래스

 

ch11 - 25 Arrays (1 / 4) - 배열을 다루기 편리한 메서드 (static) 제공

 

static 메서드가 제공되는 클래스의 예시는 아래와 같다.

Math 클래스
Object 클래스
Collections 클래스
..

 

 

 

1. 배열의 출력 - toString()

메서드의 인자로 배열을 넣으면 배열의 데이터를 문자열로 반환해준다.

만약에 배열의 데이터가 {1,2,3,4,5} 였으면,

[1,2,3,4,5] 의 형태로 보여 준다.

toString() 메서드는 이미지와 같이 오버로딩이 되어 있다.

 

 

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

System.out.println("arr = " + Arrays.toString(arr));

 

이런식으로 사용 하면 된다.

 

arr = [0, 1, 2, 3, 4]

 

암튼 이 Arrays 클래스에 있는 toString(배열) 메서드는 배열안에 있는 요소 (데이터) 를

 

모두 대괄호의 형식으로 출력해주는 기능을 가진다.

 

 

 

2. 배열의 복사 - copyOf(), copyOfRange()

위의 Arrays 클래스의 메서드 말고도 배열 복사 메서드가 있긴 하다.

System 클래스 내부에 arraycopy() 라는 메서드가 있다.

 

 

그냥 이런게 있다 정도만 체크하고 넘어가자.


암튼,

copyOf() 랑 copyOfRange() 메서드는 새로운 배열을 생성해서 반환 한다.

Range는 from ~ to 를 의미 한다.

int[] arr = {0,1,2,3,4}; 라고 할 때,

copyOfRange(arr, 2, 4) 이면 2 <= x < 4 인덱스를 의미 한다.

즉, 새로운 배열이 생성될 때 안에 요소는 2, 3 이 된다.

 

예시)

 

 

 

 

ch11 - 26 Arrays (2 / 4) - 배열을 다루기 편리한 메서드 (static) 제공

 

3. 배열 채우기 - fill(), setAll()

int[] arr = new int[5];

Arrays.fill(arr, 9); // arr = [9,9,9,9,9]

Arrays.setAll(arr, (i) -> (int) (Math.random() * 5) // arr = [1,5,2,1,1]

-> 는 람다식 이다.

Math.random() * 5 는 0 ~ 4 범위의 난수이고, + 1 을 하니까 1 ~ 5 이다.

1 <= x < 6

 

 

 

4. 배열의 정렬과 검색 - sort(), binarySearch()

sort() 메서드는 정렬 메서드 이고,

binarySearch() 메서드는 이진 탐색.

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

int index = Arrays.binarySearch(arr, 2); // index = -5 

>> 잘못된 결과

이진탐색은 반드시 정렬이 되어 있어야만 올바른 반환값을 얻을 수 있다.

>>
Arrays.sort(arr); // 배열 arr 정렬 하기.

sysout(Arrays.toString(arr)); // [0,1,2,3,4]

int index = Arrays.binarySearch(arr, 2); // index = 2 >> 올바른 결과

 

 


[ 순차 검색과 이진 검색 ]

 

 

이미지에서 숫자 10을 찾고 싶으면, 일반적으로는 0번째 인덱스 부터 차례대로 찾게 된다.

즉, 배열을 반복문을 돌려서 순차적으로 찾는것이 일반적인데 이것을 순차 검색 이라고 한다.

운이 좋으면 숫자 10을 빠르게 찾을 수 있겠지만, 숫자 10이 뒤에 있다면 조금 시간이 걸릴것이다.

그리고 만약에 배열 안에 숫자 요소가 100000000개 라면 숫자 10을 찾는게 엄청 많은 시간이 걸릴것이다.

 

 


근데 만약에 아래의 이미지와 같이 배열 데이터가 정렬이 되어 있으면 ?

 



이진 검색의 개념을 사용 해서 효율적으로 데이터를 찾을 수 있다.

숫자 10을 찾으려고 할 때,

1 부터 10 이 있다고 가정 하면, 반을 잘라내고 시작 한다.

반을 잘랐더니 숫자 5가 기준이 되었고,

찾으려고 하는 숫자 10은 기준이 된 숫자 5 보다 크기 때문에,

좌측 부분은 모두 잘라 버리고 오른쪽 부분 부터 확인 하면 된다.

좌측을 자르면 6 7 8 9 10 이 남고,

여기서 또 반을 자른다.

그러면 기준이 숫자 8이 되고, 8은 10보다 작으니까,

좌측을 또 다 잘라버린다.

그러면 9 10 만 남게 된다.

이런식으로 배열을 정렬 하고, 이진 검색 개념을 사용 하면 원하는 데이터를 

순차 검색 보다 빠르게 찾을 수 있다는 장점을 가지게 된다.

이진 검색은 둘로 나누면서 검색 한다 해서 이분 검색 이라고도 한다.

binary = 2진수의

단점은 배열이 항상 정렬이 되어있는 경우에만 사용이 가능하다는 것이다.

암튼, 정렬 속도를 높히기 위한 개념이 검색과도 연관성이 높기 때문에 중요하다고 할 수 있다.

 

 

 

ch11 - 27 Arrays (3 / 4) - 배열을 다루기 편리한 메서드 (static) 제공

 

5. 다차원 배열의 출력 - deepToString()

int[] arr = {0,1,2,3,4};
int[][] arr2D = { {11,12}, {21,22} };

sysout(Arrays.toString(arr)); // [0,1,2,3,4]
sysout(Arrays.deepToString(arr2D)); // [ [11, 12], [21, 22] ]

 

 


6. 다차원 배열의 비교 - deepEquals()

1차원 배열을 비교 할 때는 equals() 메서드를 사용 하면 되는데,

2차원 이상의 배열을 비교 해야 한다면, 이미지와 같이, deepEquals() 메서드를 사용 하면 된다.

 

 

다차원 배열을 비교 할 때,

그냥 equals() 메서드를 사용 하면 배열이 동일함에도 불구하고 false 를 반환 하게 되므로,

deepEquals() 메서드를 사용하도록 하자.

 

 

 

ch11 - 28 Arrays (4 / 4) - 배열을 다루기 편리한 메서드 (static) 제공

 

7. 배열을 List 로 변환 하기 - asList(Object... a)

(Object... a) 는 가변적인 매개변수를 의미 한다.
(개수가 정해져 있지 않는 ..)

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

List list = Arrays.asList(1,2,3,4,5); // list = [1,2,3,4,5]

만약에 list.add(6); 을 작성하고 컴파일을 돌리면 ?

UnsupportedOperationException 예외가 발생 한다.

그래서 해결 하려면, 새로운 배열리스트를 생성 하면 된다.

List list = new ArrayList(Arrays.asList(1,2,3,4,5));

그러면 해결 된다 ~

 

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

 

System.out.println(list);

 

// list.add(6); // UnsupportedOperationException

 

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

 

newList.add(6);

 

System.out.println(newList); // OK.

 

[1, 2, 3, 4, 5]

[1, 2, 3, 4, 5, 6]

 

[ 참고 ]

 

asList() 메서드를 사용해서 배열을 배열리스트로 변환 했을 때,

배열리스트로 변환이 되었지만, 반환된 리스트는 기존 배열의 주소값을 참조 하고 있다.

( asList() 메서드는 배열을 리스트로 래핑 하여 반환 한다 )

그래서, 기존 배열은 불변 리스트 이기 때문에, 크기를 변경 할 수 없는 이슈가 발생 한다.

 

따라서,

읽기는 가능 하지만, 수정을 하고 싶으면 새로운 배열리스트를 생성하고, 그 배열리스트에 배열을 복사한다.

 

그러면 배열 안에 데이터 == 요소를 새로운 배열리스트에 복사했기 때문에,

배열리스트는 가변길이의 리스트 여서 add() 메서드를 사용 할 수 있게 된다.

 

그러면 이러한 궁금증이 생기게 된다.

엥 ?

그러면 처음 부터 asList() 메서드 사용 하지 않고,

그냥 새 배열리스트 생성 하고 기존 배열에 있는 요소를 복사하는걸로 코드 작성 하면 안되나 ? 라고

틀린말은 아니지만,

asList() 메서드를 사용 하는 이유는 간편함에 있다.

새로운 배열리스트를 생성할 필요 없이,

그냥 Arrays 클래스에 있는 asList() 메서드를 사용함으로써,

편리하고 간단하게 배열을 배열리스트로 래핑 할 수 있기 때문 이다.

따라서, 단순하게 데이터를 읽기만 하는 경우 라면 (수정 X)

그냥 편리하게 asList() 메서드를 사용 하면 되겠다.

 

 


8. 람다와 스트림 관련 - parallelXXX(), spliterator(), stream()

람다와 스트림을 공부 하지 않았기에 생략.

 

 

 

예제

 

import java.util.*;

class Ex11_6 {

	public static void main(String[] args) {

		int[] arr = {0,1,2,3,4};
		int[][]	arr2D = { {11,12,13}, {21,22,23} };

		System.out.println("arr = " + Arrays.toString(arr));
		System.out.println("arr2D = " + Arrays.deepToString(arr2D));
		
		//	만약에 2차원 배열을 toString() 메서드를 사용 해서 표현 하면 ?
		//	Console 창과 같이, 이상하게 출력 된다.
		System.out.println("arr2D = " + Arrays.toString(arr2D));

		int[] arr2 = Arrays.copyOf(arr, arr.length);	//	arr2 라는 참조변수에 arr 배열을 복사 한다. 얼만큼 ? arr.length 만큼 ( == 5 )
		int[] arr3 = Arrays.copyOf(arr, 3);          
		int[] arr4 = Arrays.copyOf(arr, 7);          
		int[] arr5 = Arrays.copyOfRange(arr, 2, 4);  
		int[] arr6 = Arrays.copyOfRange(arr, 0, 7);  

		System.out.println("arr2 = " + Arrays.toString(arr2));
		System.out.println("arr3 = " + Arrays.toString(arr3));
		System.out.println("arr4 = " + Arrays.toString(arr4));
		System.out.println("arr5 = " + Arrays.toString(arr5));
		System.out.println("arr6 = " + Arrays.toString(arr6));
		
		System.out.println("===================================");

		int[] arr7 =  new int[5];
		Arrays.fill(arr7, 9);  // arr = [9,9,9,9,9]
		System.out.println("arr7 = " + Arrays.toString(arr7));

		Arrays.setAll(arr7, i -> (int) (Math.random() * 6) + 1);	//	0 ~ 5 에서 + 1 해서 1 ~ 6 범위의 난수.
		System.out.println("arr7 = " + Arrays.toString(arr7));

		System.out.println("===================================");
		
		for(int i : arr7) {
			char[] graph = new char[i];
			Arrays.fill(graph, '*');
			System.out.println(new String(graph) + i);
		}
		
		System.out.println("===================================");
		
		//	위의 for each 문과 동일 하다.
		for(int x = 0; x < arr7.length; x++) {
			int i = arr7[x];	//	숫자 요소를 int i 에 담기.
			char[] graph = new char[i];	//	i 길이 만큼 char[] 배열 생성.
			Arrays.fill(graph, '*');	//	i 길이의 배열 graph에 모두 * 로 채우기.
			
			System.out.println(new String(graph) + " [" + i + "]");	//	new String() 은 String() 의 생성자에 배열을 넣어 문자열 값을 반환.
		
			System.out.println("Arrays.toString(graph) : " + Arrays.toString(graph) + " [" + i + "]" + "\n");
		}
		
		System.out.println("===================================");

		String[][] str2D  = new String[][] { {"aaa","bbb"},{"AAA","BBB"} };
		String[][] str2D2 = new String[][] { {"aaa","bbb"},{"AAA","BBB"} };

		System.out.println(Arrays.equals(str2D, str2D2));     // false
		System.out.println(Arrays.deepEquals(str2D, str2D2)); // true
		
		System.out.println("===================================");

		char[] chArr = { 'A', 'D', 'C', 'B', 'E' };

		System.out.println("chArr = " + Arrays.toString(chArr));
		System.out.println("index of B = " + Arrays.binarySearch(chArr, 'B'));
		System.out.println("===== 이진 탐색을 사용 하려면 정렬을 해야 한다 >> 정렬 후 =====");
		Arrays.sort(chArr);
		System.out.println("chArr = " + Arrays.toString(chArr));
		System.out.println("index of B = " + Arrays.binarySearch(chArr, 'B'));
		

	}	//	main()

}	//	main Class

 

//	Console

arr = [0, 1, 2, 3, 4]
arr2D = [[11, 12, 13], [21, 22, 23]]
arr2D = [[I@5e91993f, [I@1c4af82c]
arr2 = [0, 1, 2, 3, 4]
arr3 = [0, 1, 2]
arr4 = [0, 1, 2, 3, 4, 0, 0]
arr5 = [2, 3]
arr6 = [0, 1, 2, 3, 4, 0, 0]
===================================
arr7 = [9, 9, 9, 9, 9]
arr7 = [6, 3, 6, 1, 4]
===================================
******6
***3
******6
*1
****4
===================================
****** [6]
Arrays.toString(graph) : [*, *, *, *, *, *] [6]

*** [3]
Arrays.toString(graph) : [*, *, *] [3]

****** [6]
Arrays.toString(graph) : [*, *, *, *, *, *] [6]

* [1]
Arrays.toString(graph) : [*] [1]

**** [4]
Arrays.toString(graph) : [*, *, *, *] [4]

===================================
false
true
===================================
chArr = [A, D, C, B, E]
index of B = -2
===== 이진 탐색을 사용 하려면 정렬을 해야 한다 >> 정렬 후 =====
chArr = [A, B, C, D, E]
index of B = 1

 

정리 :

 

1)

2차원 배열을 표현할 때, deepToString() 대신에 toString() 을 사용 하면 아래와 같이 원하지 않는 값이 출력 된다.

 

arr2D = [[I@5e91993f, [I@1c4af82c]

 

2)

배열을 표현 할 때, String 클래스의 생성자를 사용해서 표현 하면, 배열의 데이터가 문자열로 표현 되고,

 

Arrays 클래스의 toString 메서드를 사용하면 [ ] 대괄호의 표현 방법으로 요소들이 출력 된다.

 

3)

Arrays.binarySearch() 메서드를 사용 하려면, 반드시 sort() 메서드를 사용해서 배열을 정렬 하고 해야 한다.

 

안그러면 결과값이 원치 않는 값이 나오게 된다.

 

반응형

'Java의 정석 > 컬렉션 프레임워크' 카테고리의 다른 글

HashSet (1)  (0) 2023.09.20
Comparator & Comparable  (0) 2023.09.20
Iterator, Enumeration / Map 과 Iterator  (0) 2023.09.20
Stack / Queue (스택 / 큐)  (0) 2023.09.17
LinkedList 와 ArrayList 의 비교  (0) 2023.09.17