자료구조/JAVA

01-2)배열 리스트<제네릭>

_Jin_ 2023. 4. 15.

<쉽게 배우는 자료구조 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

댓글