<쉽게 배우는 자료구조 with 자바>를 읽으며 학습한 내용을 정리하는 중 입니다.
앞서 학습한 배열 리스트를 이번에는 제네릭을 이용하여 구현하는 과정을 작성해보겠습니다.
먼저, 제네릭을 사용할 경우 필요한 인터페이스를 먼저 작성해보자.
package list;
public interface ListInterFace<E> {
public void add(int i, E x);
public void append(E x);
public E remove(int i );
public boolean removeItem(E x);
public E get(int i);
public void set(int i, E x);
public int indexOf(E x);
public int len();
public boolean isEmpty();
public void clear();
}
앞선, 배열리스트를 구한 것과 똑같이 필요한 메서드는 같다.
다만, 제네릭을 통하여 얻을 수 있는 이점은 컴파일 타임에 타입을 체크하기에 객체에 대한 안정성을 높일 수 있고, 재사용성 증가가 있다.
package list;
public class ArrayList<E> implements ListInterFace<E> {
private E item[];
private int numitems;
private static final int DEFAULT_CAPACITY = 64;
// 생성자 1
public ArrayList() {
item = (E[]) new Object[DEFAULT_CAPACITY];
}
// 생성자 2
public ArrayList(int n) {
item = (E[]) new Object[n];
numitems = 0;
}
// 배열 리스트의 k번째 자리에 원소 x 삽입하기
public void add(int index, E x) {
if(numitems >= item.length || index < 0 || index> numitems -1 ) {
/* 예외처리 */
} else {
for ( int i =numitems-1; i>=index; i--) {
item[i-1] =item[i]; // 우시프트
}
item[index] = x;
numitems++;
}
}
//배열 리스트의 맨 뒤에 원소 추가하기
public void append(E x) {
if(numitems >= item.length) {
/*예외처리*/
} else {
item[numitems++] = x;
}
}
//배열 리스트의 k번째 원소 삭제하기
public E remove(int index) {
if(index < 0 || isEmpty() || index >= numitems -1)
return null;
else {
E tmp = item[index];
for(int i =index; i <= numitems-2; i++) {
item[i] = item[i+1]; //좌시프트
}
numitems--;
return tmp;
}
}
//배열 리스트에서 원소 x 삭제하기
public boolean removeItem(E x) {
int k =0;
while(k < numitems && ((Comparable)item[k]).compareTo(x) !=0 )
k++;
if(k==numitems)
return false;
else {
for(int i =k; i<= numitems-2; i++)
item[i] = item[i+1];
numitems--;
return true;
}
}
// 리스트의 index번째 원소 알려주기
public E get(int index) {
if( index >=0 && index < numitems)
return item[index];
else
return null;
}
// 배열리스트의 index번째 원소를 x로 대체하기
public void set(int index, E x) {
if(index < 0 || index >= numitems) {
/*에러처리*/
}else {
item[index] =x;
}
}
// 원소 x가 배열리스트의 몇 번째 원소인지 알려주기
public final int NOT_FOUND = -12345;
public int indexOf(E x) {
int i = 0;
for(i = 0; i<=numitems-1; i++) {
if(((Comparable)item[i]).compareTo(x) == 0 )
return i;
}
return NOT_FOUND;
}
public int len() {
return numitems;
}
public boolean isEmpty() {
return numitems == 0;
}
public void clear() {
item = (E[]) new Object [item.length];
numitems = 0;
}
}
위의 코드는 제네릭을 사용하여 ArrayList를 구현한 코드이다.
코드 중,
<1> item = (E[]) new Object [item.length];
<2> (((Comparable)item[i]).compareTo(x) == 0 )
부분이 처음에는 이해가 가지않았다.
먼저, 배열에서 new Object를 사용해줌에도 앞에 (E[])로 형변환을 해주는 이유를 찾아보니,
배열은 공변하며 런타임에 실체화 되지만, 제네릭 타입은 불공변하며 런타임에 소거되어
배열 타입 안정성을 보장해줄 수 없어 제네릭 배열을 직접 생성할 수 없다고 한다.
아직 무슨 소리지 하는 중입니다..
계속 이해보려고 노력해봤지만, 아직 와닿지가 않는다. 점진적으로 아는게 많아지다보면, ?가 !로 바뀌는 순간이 올거라고 믿는다.
그리고, item[i]의 경우, 객체를 비교함에 필요한 Comparable 인터페이스로 형변환 후에, x와 비교하기 위해서 위와 같이 사용된 것이다.
'자료구조 > JAVA' 카테고리의 다른 글
01-5)연결 리스트의 확장(1) (0) | 2023.12.01 |
---|---|
01-4)배열 리스트와 연결 리스트 (0) | 2023.11.29 |
01-3)연결 리스트<제네릭> (0) | 2023.05.03 |
01-1)배열 리스트 (0) | 2023.04.10 |
01) 리스트 (0) | 2023.04.09 |
댓글