[JAVA] 컬렉션 프레임웍 : 〈 Arrays 〉 & 〈 Collections 〉

DongGyu Jung·2022년 2월 25일
0

자바(JAVA)

목록 보기
38/60
post-thumbnail

🏃‍♂️ 들어가기 앞서..

본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕

*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.



Arrays 클래스

배열을 다루는데 있어 유용한 메서드들이 정의되어 있는 클래스
같은 기능의 메서드가 배열 타입에 따라 " 오버로딩(Overloading) " 되어있음.
( 정의된 메서드 모두 static 메서드 )

① 배열 복사

copyOf() / copyOfRange()

  • copyof() : " 배열 전체 "를 복사해서 새로운 배열 생성 & 반환
    (인수로 "끝 범위" 지정 가능 : 지정된 범위의 '' 은 포함 X )

  • copyOfRange() : " 배열의 일부 "를 복사해서 새로운 배열 생성 & 반환
    ( 인수로 "시작 범위" & "끝 범위" 지정 가능 : 지정된 범위의 '' 은 포함 X )
int[] arr = {0, 1, 2, 3, 4, 5 } ;
int[] arr2 = Arrays.copyOf( arr, arr.length ) ; // [0, 1, 2, 3, 4, 5]
int[] arr3 = Arrays.copyOf( arr, 3 ) ; // [0, 1, 2]
int[] arr4 = Arrays.copyOf( arr, 7 ) ; // OutOfRange 값은 '0'으로 채움 _ [0, 1, 2, 3, 4, 5, 0]

int[] arr5 = Arrays.copyOfRange( arr, 2, 4 ) ; // [2, 3] _ 끝 포함 X
int[] arr6 = Arrays.copyOfRange( arr, 0, 7 ) ; // [0, 1, 2, 3, 4, 5, 0]

② 배열 채우기

fill()

배열의 모든 요소를 " 지정된 값 "으로 채움

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

setAll()

배열을 모두 채우는데 채울 값을 도출하는 " 함수형 인터페이스 "를 매개변수로 받음
함수에 따라 값이 생성되어 채워짐
( " 함수형 인터페이스를 구현한 객체 " or " 람다식 " )

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

③ 배열 정렬 & 검색

⊙ 정렬 : sort()

int[] arr = { 3, 1, 4, 0, 2 } ;
Arrays.sort(arr) ; // Integer에 정의된 기준에 의해 정렬 -> 오름차순 정렬
System.out.println(Arrays.toString(arr)) ; // [0, 1, 2, 3, 4]

⊙ 검색 : binarySearch() _ 이진 검색

배열에서 " 지정된 값이 저장된 위치 (index) "를 반환
★ 배열이 반드시 정렬된 상태이어야 올바른 결과
( 검색 값이 여러개 존재하면 무작위 )

int[] arr = { 3, 1, 4, 0, 2 } ;
/* 정렬 X */
int idx = Arrays.binarysearch(arr, 2); // 값 2의 index
// idx = -5 _ 정렬이 안되어 있기 때문에 잘못된 값 추출 

Arrays.sort(arr) ; // [0, 1, 2, 3, 4]
int idx = Arrays.binarysearch(arr, 2); // 정렬된 배열에서 값 2의 index
// idx = 2

이전에 TreeSet을 배웠을 때 알 수 있듯
첫 번째 요소부터 순서대로 하나씩 비교 검색하는 " 순차 검색( linear search ) "과는 달리

" 이진 검색( binary search ) "
검색 속도가 굉장히 빠르다.


④ 문자열 비교 & 출력

⊙ 출력 : toString()

  • 일차원 배열 출력 : toString()
  • 다차원 배열 출력 : deepToString()
int[] arr = {0,1,2,3,4} ;
int[][] arr2D = {{11,12},{21,22}} ;

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

⊙ 비교 : equals()

  • 일차원 배열 비교 : equals()
  • 다차원 배열 비교 : deepEquals()

* 같으면 true / 다르면 false

" 다차원 배열 "에 equals()를 사용하게 되면
저장된 내용이 같더라도

" 배열에 저장된 배열의 주소 "를 비교하게 되기 때문에
false가 나오게 된다.

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

⑤ List 변환

asList()

매개변수 타입이 " 가변인수 "이기 때문에
배열 입력이 아닌 저장할 요소들 나열하는 것도 가능하다.

asList( Object... a ) 메서드는
배열을 List에 담아 반환하는데

위와 같이 매개변수의 타입이 가변인수( ... )인 것을 알 수 있다.
즉,
배열 생성을 안하고
저장할 요소들만 나열해도 동일하게
해당 요소들로 구성된 List로 반환한다.

asList()를 통해 반환된 List는

"내용 변경"은 가능하나
크기 변경( 추가/삭제 )이 불가능하다.
( 읽기 전용 )

그렇기 때문에 크기 변경이 가능한 List로 사용하기 위해서는
새로운 ArrayList 타입 객체로 생성해야 한다.

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

/* 하지만 크기변경 _ 추가삭제가 불가능하다 */
list.add(6) ; // UnsupportedOperationException 예외 발생

/*
추가/삭제 작업이 가능한 리스트로 만들기 위해선
ArrayList타입 인스턴스로 생성해야 함.
*/
List list3 = new ArrayList(Arrays.asList(1,2,3,4,5)) ;// list3 = [1, 2, 3, 4, 5]
list.add(6) ; // list3 = [1, 2, 3, 4, 5, 6]



Collections 클래스

fill()copy(), sort(), binarySearch()등 등의 메서드들은
앞서 알아봤던 Arrays와 함께 모두 포함되어 있고 같은 기능을 하기때문에 생략


▣ 유형별 컬렉션


⊙ 동기화 :: synchronized~ ()

< 멀티 쓰레드 (multi - thread) 프로그래밍 >
▶ 하나의 객체를 여러 쓰레드동시에 접근할 수 있는 환경
▶ " 데이터 무결성 유지 "를 위해 공유되는 객체에 동기화


* 동기화 = synchronization

VectorHashtable과 같은 구버전 클래스들에는
자체적으로 동기화 처리가 되어 있는데

이는 싱글 쓰레드 프로그래밍의 경우에는 낭비가 발생한다.

위와 같은 낭비를 방지하고 개선한 것이
새로 추가된 ArrayListHashMap과 같은 클래스들이다.

처음부터 동기화를 자체적으로 처리하는 것이 아닌
" 필요할 때 java.util.Collections클래스의 동기화 메서드를 이용해서 동기화 처리 "하는 방식이다.

그 Collections 클래스의 동기화 메서드가
synchronized~ () 메서드이다.

static Collection synchronizedCollection( Collection c )
static List synchronizedList( List list )
static Set synchronizedSet( Set s )
static Map synchronizedMap( Map m )
static SortedSet synchronizedSortedSet( SortedSet s )
static SortedMap synchronizedSortedMap( SortedMap m )

/* 사용 방법 */
List synchroList = Collections.synchronizedList( new ArrayList(...) ) ; // ArrayList는 동기화 되지 않은 List

⊙ 변경불가 :: unmodifiable~ ()

컬렉션에 저장된 데이터를 보호하기 위해서 변경할 수 없게끔
" 읽기 전용 " 컬렉션 생성

멀티쓰레드 프로그래밍에서 여러 쓰레드가 하나의 컬렉션을 공유할 경우, " 손상 가능성 "이 있을 때, 사용

static Collection unmodifiableCollection( Collection c )
static List unmodifiableList( List list )
static Set unmodifiableSet( Set s )
static Map unmodifiableMap( Map m )

static SortedSet unmodifiableSortedSet( SortedSet s )
static NavigableSet unmodifiableNavigableSet( NavigableSet s )
static SortedMap unmodifiableSortedMap( SortedMap m )
static NavigableMap unmodifiableNavigableMap( NavigableMap m )

⊙ 단 하나의 객체만 저장 :: singleton~ ()

단 한 개의 객체만 저장하는 컬렉션으로 " 한개의 요소 "로 이루어져 있다.

이 또한 반환된 컬렉션은 변경할 수 없다.

static List singletonList( Object o )
static Set singleton( Object o ) // Set는 그냥 singleton
static Map singletonMap( Object key, Object value )

⊙ "한 종류"의 객체만 :: checked~ ()

" 컬렉션에 모든 종류의 객체를 저장할 수 있다. "라는 특징이
장점이긴 하나

어찌보면
이전에 알아봤던 Iterator로 표준화된 코드 등과 같이 신경써서 프로그래밍해야 한다는 불편함이 있다.

하나의 통일된 타입으로 객체들을 저장하면
해당 Collection의 각 객체에 대한 독립적인 관리와 처리가 용이해지기에
필요한 경우가 있다.

static Collection checkedCollection( Collection c, Class type )
static List checkedList( List list, Class type )
static Set checkedSet( Set s, Class type )
static Map checkedMap( Map m, Class keyType, Class valueType ) // 각 각 Type 지정

static Queue checkedQueue( Queue queue, Class type )

static SortedSet checkedSortedSet( SortedSet s, Class type  )
static NavigableSet checkedNavigableSet( NavigableSet s, Class type  )
static SortedMap checkedSortedMap( SortedMap m, Class keyType, Class valueType )
static NavigableMap checkedNavigableMap( NavigableMap m, Class keyType, Class valueType )

/* 사용 방법 */
List list = new ArrayList() ;
List checkedList = checkedList( list, String.class ) ; //String만 저장 가능하도록

checkedList.add("abc") ; // 가능
checkedList.add(new Integer(123)) ; // 불가능(에러) : ClassCastException 발생

※ 유용한 Collections 메서드

  • addAll( [배열] , ... ) : 지정 Collection 에 '입력된 값들( 가변인자 )'을 추가
  • rotate( [배열] , int move ) : 오른쪽으로 move 칸씩 이동
  • swap( [배열], int idx1, int idx2) : "idx1 위치의 값"과 "idx2 위치의 값"과 교환
  • shuffle( [배열] ) : 무작위 섞기
  • sort( [배열], reverseOrder()) : 역순 정렬 == " reverse( [배열] ) "

  • disjoint( [배열 1], [배열 2] ) : 두 배열에 " 공통요소가 있으면 " true
  • nCopies( [배열].size(), Object value ) : 지정 배열과 같은 크기의 새로운 리스트 생성 & value로 해당 리스트 채움 ( 자동 fill _ copy & fill )

" 지네릭스(Generics) "로 컬렉션에 저장할 요소 타입을 제한할 수 있지만
이 방법은 JDK1.5부터 가능한 방법이기 때문에
이전 버젼과의 호환이 되지 않는다.
(그렇기 때문에 위와 같은 checked 를 통한 타입 제한 방법을 알아두고 사용하는 것이 좋다.)

0개의 댓글