Java LinkedList - 직접 구현하기 3
직접 구현한 연결리스트에서 추가로 제네릭 도입하여 타입 안정성을 높이고, Node 객체는 외부에서 사용하지 않으므로 내부에서 사용하도록 중첩 클래스로 만든다.
- 제네릭 도입
- 중첩 클래스 사용
ClinkedList.class
public class CLinkedList<E> {
Node<E> first;
int size;
public void add(E e) {
Node<E> newNode = new Node<>(e);
if (first == null) {
// 노드를 처음으로 사용한 경우에만 수행함
first = newNode;
} else {
// 노드가 있는 경우 수행
Node<E> lastNode = getLastNode();
lastNode.next = newNode;
}
size++;
}
public void add(int index, E e) {
Node<E> newNode = new Node<>(e);
if (index == 0) {
newNode.next = first;
first = newNode;
} else {
Node<E> prevNode = getNode(index-1);
newNode.next = prevNode.next;
prevNode.next = newNode;
}
size++;
}
public E remove(int index) {
Node<E> retNode;
E item;
if (index == 0) {
retNode = first;
first = first.next;
} else {
Node<E> prevNode = getNode(index-1);
retNode = prevNode.next;
prevNode.next = prevNode.next.next;
}
item = retNode.item;
retNode.item = null;
retNode.next = null;
size--;
return item;
}
private Node<E> getLastNode() {
Node<E> n = first;
while (n.next != null) {
n = n.next;
}
return n;
}
public E set(int index, E element) {
Node<E> n = getNode(index);
E oldValue = n.item;
n.item = element;
return oldValue;
}
public E get(int index) {
Node<E> node = getNode(index);
return node.item;
}
private Node<E> getNode(int index) {
Node<E> n = first;
for (int i = 0; i < index; i++) {
n = n.next;
}
return n;
}
public int indexOf(E o) {
int index = 0;
for (Node<E> n = first; n != null; n = n.next) {
if (o.equals(n.item)) {
return index;
}
index++;
}
return -1;
}
public int size() {
return size;
}
@Override
public String toString() {
return "CLinkedList{" +
"first=" + first +
", size=" + size +
'}';
}
private static class Node<E> {
E item;
Node<E> next;
public Node(E item) {
this.item = item;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
Node<E> n = this;
sb.append("[");
while (n != null) {
sb.append(n.item);
if (n.next != null) {
sb.append("->");
}
n = n.next;
}
sb.append("]");
return sb.toString();
}
}
}
- CLinkedList<E> 제네릭 클래스로 선언
- Object 타입이 없도록 타입 및 파라미터 <E> 로 변경
- 정적 중첩 클래스로 새로 Node<E> 제네릭 타입으로 선언
중첩 클래스 사용
- 클래스 안에 클래스로 선언한 것이 중첩 클래스.
- 중첩 클래스는 중첩 클래스 안에서만 사용.
- Node 클래스는 CLinkedList 안에서만 사용하고 외부에 공개할 이유 없음.
- 중첩 클래스는 클래스 안에 있으므로 선언을 은닉함.
- 외부의 Node 클래스보다 내부의 Node 클래스로 우선 사용으로 패키지 관리 수월.
Main.class - 출력하기
System.out.println("** String LinkedList **");
CLinkedList<String> strList = new CLinkedList<>();
strList.add("A");
strList.add("B");
strList.add("C");
String str = strList.get(0);
System.out.println(str);
System.out.println(strList);
System.out.println(strList.first);
System.out.println();
System.out.println("** Integer LinkedList **");
CLinkedList<Integer> intList = new CLinkedList<>();
intList.add(100);
intList.add(200);
intList.add(300);
Integer num = intList.get(0);
System.out.println(num);
System.out.println(intList);
System.out.println(strList.first);
** String LinkedList **
A
CLinkedList{first=[A->B->C], size=3}
[A->B->C]
** Integer LinkedList **
100
CLinkedList{first=[100->200->300], size=3}
[A->B->C]