4. 배열 리스트
1) 배열은 한 번 생성하면 절대로 길이를 변경할 수 없다. 이 때 java.util 패키지의 ArrayList 클래스를 사용하면 이 문제를 해결 할 수 있다.
ArrayList 객체는 내부에서 배열을 관리한다. 배열이 너무 작아지거나 배열의 공간이 많이 남으면, 다른 내부 배열을 자동으로 생성해서 원본 배열의 요소를 옮긴다. 이 과정은 개발자에게는 보이지 않게 진행된다.
2) ArrayList 제네릭 클래스(타입 파라미터를 받는 클래스)
ArrayList<String> list = new ArrayList<>(); //new ArrayList<String>();
<> 부분이 비어있는데, 컴파일러는 변수의 타입으로부터 타입 파라미터를 추론한다.
호출 인자가 없지만, 그래도 끝 부분에 ()를 붙여야 한다.
결과는 크기가 0인 배열 리스트이다.
4.1. 기본 타입의 래퍼 클래스
제네릭 클래스에는 불편한 제약이 하나 있는데, 바로 기본 타입을 타입 파라미터로 사용할 수 없다는 것이다.
해결책으로 래퍼 클래스를 사용한다. 기본 타입과 그에 대응하는 래퍼 타입 사이의 변환은 자동으로 일어난다.
** ==와 != 연산자는 객체의 내용이 아니라 객체 참조를 비교한다. numbers.get(i) == numbers.get(j)는 인덱스 i와 j에 있는 두 숫자가 같은지 검사하지 않는다. 래퍼 객체를 이용해서 문자열처럼 equals 메서드를 호출해야 한다.
4.2. 배열과 배열 리스트 복사하기
배열 변수를 또 다른 배열 변수로 복사할 수 있지만, 그렇게 하면 두 변수가 같은 배열을 참조한다.
int[] a = {1, 2, 3, 4, 5};
int[] b = {6, 7, 8, 9, 10};
System.out.println(a[4]); //5
System.out.println(b[4]); //10
a = b; //같은 주소값을 가진다.
System.out.println(a[4]); //10
System.out.println(b[4]); //10
a[4] = 999;
System.out.println(a[4]); //999
System.out.println(b[4]); //999
이런 공유를 원하지 않는다면 Arrays.copyOf를 이용하여 배열의 사본을 만들어야 한다.
Arrays.compyOf 메서드는 새로운 배열을 원하는 길이로 생성하고원본 배열의 요소를 복사한다.
int[] c = {11, 12, 13, 14, 15};
System.out.println(c[4]); //15
int[] d = Arrays.copyOf(c, c.length);
System.out.println(c[4]); //15
System.out.println(d[4]); //15
d[4] = 999;
System.out.println(c[4]); //15
System.out.println(d[4]); //999
ArrayList역시 내부에 배열을 이용하기 때문에 배열과 같은 방식으로 동작한다.
배열 리스트 역시 복사하려면 기존 배열 리스트에서 새로운 배열 리스트를 생성해야 한다.
List<String> cList = new ArrayList<>();
cList.add(0, "c-array");
System.out.println(cList.get(0)); //c-array
List<String> dList = new ArrayList<>(cList);
cList.set(0, "new-c-array");
dList.set(0, "d-array");
System.out.println(cList.get(0)); //new-c-array
System.out.println(dList.get(0)); //d-array
배열을 배열 리스트로 복사할 수 있다. 이 때도 ArrayList 생성자를 사용할 수 있다.
String[] names2 = {"홍길동", "홍길순"};
ArrayList<String> namesArr = new ArrayList<>(Arrays.asList(names2));
System.out.println(namesArr.get(0)); //홍길동
4.3. 배열 알고리즘
1) 배열이나 배열 리스트 정렬할 때는 sort 메서드를 사용, fill을 사용하여 배열값을 초기화 할 수 있다.
String[] names3 = new String[2];
Arrays.fill(names3, "abc");
System.out.println(names3[0]); //abc
System.out.println(names3[1]); //abc
List<String> list = new ArrayList<>(2);
list.add("a");
list.add("b");
Collections.fill(list, "def");
System.out.println(list.get(0)); //def
System.out.println(list.get(1)); //def
2) 요소들을 임의로 섞을 땐 shuffle, 요소들을 뒤집을 땐 reverse를 활용한다.
list.set(0, "박");
list.set(1, "보");
list.set(2, "검");
Collections.shuffle(list);
System.out.println(list.toString());
Collections.reverse(list);
System.out.println(list.toString());
4.4. 가변인자
호출하는 쪽에서 인자 개수를 정하지 않고 사용할 수 있는 메서드가 몇 가지 존재한다.
그 중 대표적인 메서드가 printf이다.
'타입... 변수명'으로 선언한 파라미터는 배열로 처리된다.
메서드가 호출될 때 배열이 생성되고, 전달한 인자들로 채워진다.
따라서 메서드 구현부에서는 배열처럼 사용하면 된다.
public static void main(String[] args) {
System.out.println(average(0, 1, 2, 3, 4, 5)); //2.0
}
public static double average(int... values) {
int sum = 0;
for(int v : values) sum += v;
return values.length == 0 ? 0 : sum / values.length;
}
* 가변 파라미터는 반드시 메서드의 마지막 파라미터여야 한다. 하지만 다른 파라미터들은 가변 파라미터 앞에 둘 수 있다.
(위 이미지 printf 파라미터 참고)
참고: 카이호스트만의 코어자바8
'DEV > Java' 카테고리의 다른 글
[자바] 사용자 정의 예외 만들기 (2) | 2023.02.01 |
---|---|
[자바] default method 와 static method (2) | 2023.02.01 |
[자바] 3. 문자열 (1) | 2022.01.13 |
[자바] 2. 자료형 & 연산자 (0) | 2022.01.13 |
[자바] 1. 기본 프로그래밍 구조 (0) | 2022.01.11 |
댓글