티스토리 뷰
배열과 ArrayList 차이
자바에서 배열은 C 언어와 마찬가지로 동일한 타입의 값을 연속하여 정해진 크기만큼 저장하는 자료구조다. 대신 C 언어와의 차이라면 자바 배열은 배열의 참조 선언과 실제 배열의 할당이 분리되어야 하며, 배열은 반드시 new를 통해 할당되어야 한다는 점이다.
int nArray[] = new int[20];
String strArray[] = null;
...
strArray = new String[maxStringCnt];
배열의 문제점은 new로 할당된 크기를 벗어나서 배열에 값을 넣거나 접근하면 ArrayIndexOutOfBoundsException라는 예외가 나게 된다는 점이다. 즉 배열은 필요한 크기만큼 동적할당하는데, 한번 할당하면 그 크기를 넘어가게 사용할 수 없다. 입력을 받으면서 0이 나올 때까지 배열에 값을 추가하는 다음 코드에서 배열의 크기에 관해 두 가지 작업이 필요하다. 배열에 실제 저장된 데이터의 개수를 따로 기억해야 하고 매번 개수가 배열 크기를 넘어가지 않는지 검사해야 한다.
int nArray[] = new int[20];
int num = 0, cnt=0;
for (int i = 0; i < 20; i++) {
num = scan.nextInt();
if (num == 0) {
cnt = i+1;
break;
}
nArray[i] = num;
}
if (num != 0) {
cnt = 20;
System.out.println("20개가 넘는 숫자가 입력되었습니다. 20개까지만 저장됩니다.");
}
for (int i = 0; i < cnt; i++)
System.out.print(" " + nArray[i]);
System.out.println();
첫 번째 문제는 배열의 크기와 들어있는 값의 개수가 일치하지 않을 수 있다는 점이다. 항상 정해진 개수의 데이터만 저장하는 경우라면 개수만큼 배열을 생성하면 되고 그 경우 따로 개수를 기억할 필요없이 배열의 길이를 개수로 사용하면 된다. 그러나 앞의 예처럼 개수를 미리 알지 못하는 경우 우리는 두 가지 점에서 불편함을 겪게 된다.
- 배열을 최대 크기로 할당해야 한다. (최대 크기가 얼마일지 예상해야 한다. 혹시 늘어나면 프로그램을 고쳐서 값을 수정해야 한다.)
- 실제 값의 개수를 따로 저장해야 한다.
그러므로 배열을 사용할 때 미리 개수를 알지 못하면 최대 크기의 문제와 실제 값의 개수를 관리하는 문제를 프로그래머가 직접 신경써야 한다. 이러한 문제를 해결하는 것이 ArrayList라고 할 수 있다.
ArrayList 기본사용법
ArrayList는 배열의 기능을 제공하는 라이브러리 클래스로 크기와 개수에 대해 프로그래머가 신경쓰지 않고 여러 개의 값을 저장하는 자료구조와 연산을 제공한다.
ArrayList<Integer> nList = new ArrayList<>();
while (true) {
num = scan.nextInt();
if (num == 0) break;
nList.add(num);
}
for (int i = 0; i < nList.size(); i++)
System.out.print(" " + nList.get(i));
System.out.println();
ArrayList는 선언할 때 어떤 타입의 값을 넣을 것인지를 꺽쇠<> 안에 정해준다. 그러면 그 타입의 원소만 들어갈 수 있는 ArrayList가 된다. 위 예에서는 Integer 타입의 값을 가지는 ArrayList를 선언했다. 선언부에서 바로 객체를 생성하여 초기화하는 경우 오른쪽의 <> 안에 타입은 왼쪽과 같으면 생략가능하다. 경우에 따라서는 참조 변수만 선언하고 null로 초기화한 후 실제 필요할 때 생성하기도 한다. (int와 Integer의 차이에 대해서는 다음글을 참고)
값을 ArrayList 끝에 추가하기 위해서는 add 메소드를 쓴다. 중간의 특정 위치에 추가하는 것은 add(index, elem); 형태가 된다.
int nArray[] = {1, 2, 3, 4, 5};
nList = new ArrayList(Arrays.asList(nArray));
nList.add(3, 10); // [1, 2, 3, 10, 4, 5]
nList.remove(2); // [1, 2, 10, 4, 5]
nList.add(20); // [1, 2, 10, 4, 5, 20]
ArrayList의 값을 꺼내기 위해서는 get 메소드를 이용할 수 있다. 예를 들어 3번 인덱스에 저장된 값을 가져오기 위해서는 nList.get(3)와 같이 호출할 수 있다. 다음 예에서는 사용자가 입력한 값은 1부터 시작하는 pos 번째를 요청한 것이므로 get(pos-1)을 통해 0부타 시작하는 인덱스로 바꾸어주었다.
pos = scan.nextInt();
System.out.printf("%d번째 값은 %d 입니다.%n", pos, nList.get(pos-1)); // 3번재 값은 10입니다.
주어진 값이 ArrayList의 몇 번째에 들어있는 값인지 출력하는 기능은 indexOf 메소드를 이용하여 다음과 같이 작성할 수 있다. 여기서 indexOf는 매개변수로 받은 값이 해당 ArrayList의 몇 번째 요소인지를 돌려주는 메소드다. 10이라는 값이 위 nList 에서 2번 인덱스에 들어있으므로 pos는 2가 된다.
int pos = nList.indexOf(10); // pos는 2가 된다
ArrayList를 쓸 때 한가지 주의할 사항으로 리스트의 모든 요소를 차례로 반복할 때는 for (int i = 0; i < list.size; i++) ... 형태의 루프를 사용하기 보다는 for (String s : list) 이런 형태의 foreach루프를 쓰는 것이 좋다.
ArrayList<String> strList = new ArrayList<>();
... // strList에 값을 추가
for (String s : strList)
System.out.print(s);
리스트에 값을 추가하거나 삭제하는 (요소가 변경되는) 루프의 경우는 index를 사용하는 for나 while 루프를 써야 한다. 그러나 리스트에 있는 모든 값을 차례로 읽으면서(순차 방문) 하는 계산은 모두 foreach 루프를 쓰는 것이 코드의 가독성을 높여줄 뿐 아니라 효율성에서도 더 낫다.
활용 예제
입력에서 문자열을 읽어 중복되지 않은 단어를 모두 출력하는 프로그램을 생각해 보자.
ArrayList<String> strList = new ArrayList<>();
while (scan.hasNext()) {
word = scan.next();
if (strList.contains(word))
continue;
strList.add(word);
}
for (String s : strList)
System.out.print(" " + s);
System.out.println();
이 프로그램을 실행하면 입력을 모두 읽어 새로 나온 단어면 리스트의 제일 끝에 추가한다. 두번째 나온 단어 부터는 추가되지 않는다.
입력 : one two three one two one
출력 : one two three
위의 프로그램을 고쳐서 문자열을 읽어 중복되면 앞의 것을 제거하고 새로 나온 것을 제일 뒤에 넣도록 바꾸어 보자. 위의 프로그램에서 if ... continue 대신에 해당 요소를 삭제하는 remove를 넣어주면 된다. remove는 인덱스를 주면 해당 위치의 값을 삭제하고 요소 타입의 매개변수를 주면 그 요소를 찾아서 있으면 삭제한다. (있으면 삭제하고 true를 반환, 없으면 false를 반환)
strList.remove(word);
이번에는 뒤에 나온 단어가 추가된 결과가 나오는데, 위의 동일한 입력에 대해 실행 결과는 다음과 같다.
입력 : one two three one two one
첫번째 출력 : one two three
두번째 출력 : three two one
'자바 프로그래밍' 카테고리의 다른 글
자바 콜렉션 (3) - 해시맵 응용 예제 (0) | 2019.01.13 |
---|---|
자바 콜렉션 (2) - HashMap (0) | 2019.01.13 |
객체 clone과 깊은/얕은 복사 (0) | 2019.01.12 |
자바 스트링 제대로 알기 (3) - 스트링의 불변성과 StringBuilder (0) | 2019.01.12 |
자바 스트링 제대로 알기 (2) - 포매팅 (0) | 2019.01.12 |
- Total
- Today
- Yesterday
- 지연계산
- C++ 클래스
- Camel Style
- 이터러블
- CompareTo
- sort key
- 패턴
- ToString
- 콜렉션
- python example
- comparable
- contentEquals
- contains
- python exercise
- max
- Iterator
- 스트링 +
- follow
- indexof
- APPEND
- rust
- TypeError
- 자바regex
- format
- typedef
- zip
- 동적바인딩
- 스트링
- Lazy evaluation
- 이터레이터
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |