Unicorns

All the things

ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java Study] - LinkedList , Queue in Collection framework
    Java 2021. 9. 26. 16:23

    LinkedList는  java Collection framework에서 List 인터페이스를 구현한 클래스로 List 인터페이스로 사용 가능한 컬렉션입니다.

     

    출처 : https://howtodoinjava.com/java/collections/java-linkedlist-class/

     

     

    LinkedList에는 Node로 불리는 요소가 있는데요 

     

    요소는 데이터와 다음 Node의 주소값 2가지로 나눌 수 있습니다.

     

    • Head 는 오직 리스트의 첫번째 요소 주소값 만 가지고 있습니다.
    • 리스트의 마지막 요소는 노드의 주소 값 부분이 null 입니다.

     

    이렇게 이전요소와 다음요소가 직접적으로 연결된 데이터 구조를 linear data strucure(선형 자료구조) 라고 합니다.

    LinkedList 는 대표적인 선형 자료구조 중 하나입니다.

     

    위의 예시는 타입을 Integer 으로 지정 했을 때이다.

    데이터 값은 모두 Integer

     

     

    메서드

     

    LinkedList 에서 메서드 중 일부를 살펴보면

    • boolean add(Object o ) : 리스트의 마지막 부터 해당 요소를 추가한다.
    • void add(int index , Object element) : 지정한 index 위치에 요소를 추가한다.
    • void addFirst(Objct o) : 리스트의 첫번째에 해당 요소를 추가한다.
    • void addLast(Object o) : 리스트의 제일 마지막에 요소를 추가한다.
    • int size() : 리스트에 들어 있는 요소 개수를 반환 한다.
    • boolean contains(Object o) : 리스트에 해당 요소가 있으면 true , 그렇지 않으면 false 를 반환한다.
    • boolean remove(Object o) : 리스트에 해당 요소를 삭제한다.
    • int indexOf(Object o) : 해당 요소가 리스트의 몇 번째 인덱스에 있는지 반환한다. 만약 없으면 -1을 반환한다.

     

    ※ add(Object o) , addLast(Object o) 메서드의 차이점은 무엇일 까?

    두 메서드는 동일한 기능을 수행하는데 ,

    차이점은 add(Object o) 는 수행이 잘 되었는지 boolean 값을 반환하고,

    addLast(Object o)는 아무 값도 반환하지 않는다.

     

    또 하나는,

    add(Object o) 는 Collection 인터페이스 안에 선언되어 있기 때문에 , 

    List 인터페이스를 구현한 클래스 와 Queue 인터페이스를 구현한 클래스에서 전부 사용 할 수 지만

     

    addLast(Object o) 는 Deque interface 안에 선언되어 있기 때문에 

    Deque interface를 구현한 클래스만 사용할 수 있다.

     

    즉 사용 범위가 다른 것이다.

     

    reference 

    https://www.codekru.com/java/linked-list-addfirst-and-addlast-methods

     

     

    구현 해보기

    #1

     

     

     

     

    #2 

     

     

    public class ListNode<E> {
        private int size;
        private Node head;
    
        class Node {
            E data;
            Node next;
    
            public Node(E data) {
                this.data = data;
                this.next = null;
            }
    
            public Node(E data, Node next) {
                this.data = data;
                this.next = next;
            }
    
        }
    
        public ListNode() {
            head = null;
            size = 0;
        }
    
        boolean add(E data) {
            // list가 비어 있으면 head node 에 첫 번째 node 값을 할당한다.
            if (head == null) {
                head = new Node(data);
            } else { // list에 값이 있다면
                Node node = head; // 리스트 연결을 위한 임시 노드
                while (node.next != null) { // 리스트의 마지막 까지 반복
                    node = node.next;
                }
                node.next = new Node(data);
            }
            size++;
            return true;
        }
    
        void add(int index, E data) {
            if (index == 0) {
                head = new Node(data, head);
            } else {
                Node node = getNode(index-1);
                node.next = new Node(data , node.next);
            }
            size++;
        }
    
        Node getNode(int index) {
            if (index < 0 || index >= size) {
                throw new IndexOutOfBoundsException();
            }
            Node node = head;
            for (int i = 0; i < index; i++) {
                node = node.next;
            }
            return node;
        }
    }

     

      public static void main(String[] args) {
           	ListNode listNode = new ListNode();
            listNode.add(11);
            listNode.add(22);
            listNode.add(33);
        }

     

     

     

     

    Queue

    Queue 인터페이스는 FIFO(First-In First-Out) 자료구조에서 사용되는 메서드를 정의하고 있다.

     

     

    위에서 살펴본 LinkedList가 Queue 인터페이스를 구현한 대표적인 클래스다.

     

    메서드 설명
    boolean add(E e) queue 에 해당 원소를 넣는다.  성공하면 true를 리턴하고 실패 하면  예외가 발생한다.
    boolean offer(E e) queue 에 해당 원소를 넣는다. 성공하면 true를 리턴하고 실패 하면 false 를 리턴한다.
    E element() queue 의 head를 리턴한다.  만약 queue가 비어 있다면 예외가 발생한다. 
    E peek() queue 의 head를 리턴한다.  만약 queue가 비어 있다면 null 을 리턴한다. 
    E remove() queue 의 head를 리턴하고 , queue에서 제거한다. 만약 queue가 비어 있다면 예외가 발생한다. 
    E poll() queue 의 head를 리턴하고, queue에서 제거한다. 만약 queue가 비어 있다면 null을 리턴한다. 
    boolean isEmpty() queue 가 비어있는지 확인 한다.  비어있으면 true , 데이터가 있으면 false 를 리턴 한다.

     

    public class Example {
        public static void main(String[] args) {
            // 정수 값 담는 queue 생성
            Queue<Integer> queue = new LinkedList<>();
            queue.add(10); // 정수 10을 queue 에 넣는다.
            queue.add(20); // 정수 20을 queue 에 넣는다
            queue.add(30); // 정수 30을 queue 에 넣는다.
            queue.add(40);
            queue.add(50);
            queue.add(60);
            queue.add(70);
            System.out.println(queue.element()); // 10 을 반환
            System.out.println(queue.peek()); // 10을 반환
            System.out.println(queue.remove()); // 10울 반환하고  10을 queue 에서 제거한다.
            System.out.println(queue.peek()); //위에서 10을 제거 했기 때문에 20을 반환
            System.out.println(queue.poll()); // 20을 반환하고 20을 queue 에서 제거한다.
            System.out.println(queue.isEmpty()); // queue에 data 가 있으므로 false;
        }
    }

     

    예외가 발생하는 경우 - element() , remove()

    public class Example {
        public static void main(String[] args) {
            // 정수 값 담는 queue 생성
            Queue<Integer> queue = new LinkedList<>();
            System.out.println(queue.element()); // java.util.NoSuchElementException 발생
        }
    }

    NoSuchElementException 발생 (Runtime Exception)

    public class NoSuchElementException extends RuntimeException {
        private static final long serialVersionUID = 6769829250639411880L;
    
        /**
         * Constructs a {@code NoSuchElementException} with {@code null}
         * as its error message string.
         */
        public NoSuchElementException() {
            super();
        }
    
        /**
         * Constructs a {@code NoSuchElementException}, saving a reference
         * to the error message string {@code s} for later retrieval by the
         * {@code getMessage} method.
         *
         * @param   s   the detail message.
         */
        public NoSuchElementException(String s) {
            super(s);
        }
    }
    public class Example {
        public static void main(String[] args) {
            // 정수 값 담는 queue 생성
            Queue<Integer> queue = new LinkedList<>();
            System.out.println(queue.remove()); //java.util.NoSuchElementException 발생
        }
    }

     

    null 을 반환하는 경우 - peek() , poll()

    public class Example {
        public static void main(String[] args) {
            // 정수 값 담는 queue 생성
            Queue<Integer> queue = new LinkedList<>();
            System.out.println(queue.peek()); // null 반환
        }
    }
    public class Example {
        public static void main(String[] args) {
            // 정수 값 담는 queue 생성
            Queue<Integer> queue = new LinkedList<>();
            System.out.println(queue.poll()); // null 반환
        }
    }

     

     

    양방향 queue 에 해당하는 LinkedList

    위에서 살펴본 queue 는 FIFO 자료구조로 데이터를 넣고 제거하는 것이 한쪽으로만 가능했다. (단 방향)

    이에 비해 LinkedList 는 양방향으로 데이터를 넣고 제거하는 것이 가능하다.

    그림으로 살펴보면

     

    위에서 살펴본 queue 메서드를 포함하여 LinkedList 클래스에 추가 된 것이

    메서드 설명
    addFirst() queue 의 시작 지점에  해당 요소를 넣는다.
    addLast() queue 의 끝 지점에 해당 요소를 넣는다.
    peekFirst() queue 의 시작 지점에 있는 해당 요소를 리턴한다.
    peekLast() queue 의 끝 지점에  해당 요소를 리턴한다.
    pollFirst() queue 의 시작 지점에 있는 해당 요소를 리턴하고 , 요소를 삭제한다.
    pollLast() queue 의 끝 지점에 있는 해당 요소를 리턴하고 , 요소를 삭제한다.

     

    이다. 

    public class Example {
        public static void main(String[] args) {
            LinkedList<Integer> queue = new LinkedList<>();
            queue.add(10);
            queue.add(20);
            queue.add(30);
            queue.addFirst(40); // LinkedList 시작점에 원소를 추가
            queue.add(50);
            System.out.println(queue); // [40 , 10 , 20 ,30 ,50]
            System.out.println(queue.peekLast()); // 50
            System.out.println(queue.peekFirst()); // 40
        }
    }

     

     

    public class Example {
        public static void main(String[] args) {
            LinkedList<Integer> queue = new LinkedList<>();
            queue.add(10);
            queue.add(20);
            queue.add(30);
            queue.addFirst(40); // LinkedList 시작점에 원소를 추가
            queue.add(50);
            System.out.println(queue); // [40 , 10 , 20 ,30 ,50]
            System.out.println(queue.pollFirst()); // 40을 리턴하고 queue 에서 40을 제거
            System.out.println(queue); // [10, 20, 30, 50]
            System.out.println(queue.pollLast()); // 50을 리턴하고 queue 에서 50을 제거
            System.out.println(queue); // [10, 20, 30]
        }
    }

     

     

     

     

     

     

     

    REFERENCE

    https://www.geeksforgeeks.org/linked-list-set-1-introduction/
    https://beginnersbook.com/2013/12/linkedlist-in-java-with-example/
    https://www.upgrad.com/blog/what-is-linear-data-structure/
    https://www.programiz.com/java-programming/queue
    이것이 자바다

     

    댓글

Designed by Tistory.