LinkedList - 직접 구현하는 연결 리스트4 - 제네릭 도입

2024. 5. 22. 07:13김영한 Java/컬렉션 프레임워크

지금까지 만든 연결 리스트에 제네릭을 도입해서 타입 안정성을 높여보자.

추가로 여기서 사용하는 Node는 외부에서 사용되는 것이 아니라 연결 리스트 내부에서만 사용된다. 따라서 중첩 클래스로 만들자.

package collection.link;

public class MyLinkedListV3<E> {
    private Node<E> first;
    private int size = 0 ;

    public void add(E e){
        Node<E> newNode = new Node<E>(e);
        if(first == null){
            first = newNode;
        }else{
            Node<E> lastNode = getLastNode();
            lastNode.next=newNode;
        }
        size++;
    }

    public int size() {
        return size;
    }

    private Node<E> getLastNode() {
        Node<E> x = first;
        while(x.next!=null){
            x=x.next;
        }
        return x;
    }

    //추가코드
    public void add(int index, E e){
        Node<E> newNode = new Node(e);
        if(index ==0){
            newNode.next=first;
            first=newNode;
        }else{
            Node<E> prev = getNode(index - 1);//직전 노드를 찾는것
            newNode.next=prev.next;
            prev.next=newNode;
        }
        size++;
    }

    //추가 코드
    public Object remove(int index){
        Node<E> removeNode = getNode(index);
        E removedItem = removeNode.item;
        if(index==0){
            first = removeNode.next;
        }else{
            Node prev = getNode(index - 1);
            prev.next=removeNode.next;
        }
        removeNode.item=null;
        removeNode.next=null;
        size--;
        return removedItem;
    }

    public E set(int index, E element){
        Node<E> x = getNode(index);
        E oldValue = x.item;
        x.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> x = first;
        for (int i = 0; i < index; i++) {
            x=x.next;
        }
        return x;
    }

    public int indexOf(E o) {
        int index = 0;
        for (Node<E> x = first; x != null; x = x.next) {
            if (o.equals(x.item))
                return index;
            index++;
        }
        return -1;
    }

    @Override
    public String toString() {
        return "MyLinkedListV1{" +
                "first=" + first +
                ", size=" + size +
                '}';
    }

    private static class Node<E>{
        E item;
        Node next;

        public Node(E item) {
            this.item = item;
        }


        //[A->B->C]
        @Override
        public String toString() {
            StringBuilder sb = new StringBuilder();
            Node<E> x = this;
            sb.append("[");
            while(x!=null){
                sb.append(x.item);
                if(x.next!=null) {
                    sb.append("->");
                }
                x= x.next;
            }
            sb.append("]");
            return sb.toString();
        }
    }
}
  • MyLinkedListV3<E>로 제네릭 클래스를 선언했다.
  • Object로 처리하던 부분을 타입 매개변수 <E>로 변경했다.
  • 정적 중첩 클래스로 새로 선언한Node<E>도 제네릭 타입으로 선언했다.

 

중첩 클래스

  • 중첩 클래스는 특정 클래스 안에서만 사용될 때 주로 사용한다.
  • Node클래스는 MyLinkedList안에서만  사용된다. 외부에서는 사용할 이유가 없다.
  • 이럴 때 중첩 클래스를 사용하면 특정 클래스 안으로 클래스 선언을 숨길 수 있다.
  • 중첩 클래스를 사용하면 MyLinkedListV3입장에서 외부에 있는 Node 클래스보다 내부에 선언한 Node클래스를 먼저 사용한다.