
ArrayList는 내부에 배열을 사용해서 데이터를 보관하고 관리한다.
데이터 추가시 기존 데이터들 오른쪽 이동
데이터 삭제시 기존 데이터들 왼쪽 이동
이렇게 앞이나 중간에 데이터를 추가하거나 삭제하는 경우 많은 데이터를 이동하기 때문에 성능이 좋지 않다.
낭비되는 메모리 없이 필요한 만큼만 메모리를 확보해서 사용한다.
노드를 만들고 각 노드를 서로 연결하는 방식이다.
public class Node {
Object item;
Node next;
}
노드 클래스는 내부에 저장할 데이터 item 과, 다음으로 연결할 노드의 참조인 next 를 가진다.
노드와의 연결 구조를 통해 리스트로 만든 자료 구조가 LinkedList 이다.
public class MyLinkedList<E> {
private Node<E> first;
private int size = 0;
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++;
}
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 E remove(int index) {
Node<E> node = getNode(index);
E removedItem = node.item;
if (index == 0) {
first = node.next;
} else {
Node<E> prev = getNode(index - 1);
prev.next = node.next;
}
node.next = null;
node.item = 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) {
return getNode(index).item;
}
public int indexOf(E e) {
int index = 0;
for (Node<E> x = first; x != null; x = x.next) {
if (x.item.equals(e)) return index;
index++;
}
return -1;
}
public int size() {
return size;
}
@Override
public String toString() {
return "MyLinkedListV1{" +
"first=" + first +
", size=" + size +
'}';
}
private Node<E> getNode(int index) {
Node<E> x = first;
for (int i = 0; i < index; i++) {
x = x.next;
}
return x;
}
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> 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();
}
}
}
private Node<E> first첫 노드의 위치를 가리킨다.
private int size = 0 자료 구조에 입력된 데이터의 사이즈이다.
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++;
}
private Node<E> getLastNode() {
Node<E> x = first;
while (x.next != null) {
x = x.next;
}
return x;
}
while (x.next != null)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++;
}
private Node<E> getNode(int index) {
Node<E> x = first;
for (int i = 0; i < index; i++) {
x = x.next;
}
return x;
}
index == 0 이면
newNode.next = first; 다음 노드에 현재 첫 노드를 옮기고
first = newNode; newNode를 첫 노드로 수정한다.
getNode(index - 1); : 추가하려는 index 앞의 노드를 찾아서 새롭게 추가하는 노드를 가리키도록 하고, 추가되는 노드는 prev 노드가 가리키던 노드를 가리키도록 수정한다.
public E remove(int index) {
Node<E> node = getNode(index);
E removedItem = node.item;
if (index == 0) {
first = node.next;
} else {
Node<E> prev = getNode(index - 1);
prev.next = node.next;
}
node.next = null;
node.item = null;
size--;
return removedItem;
}
private Node<E> getNode(int index) {
Node<E> x = first;
for (int i = 0; i < index; i++) {
x = x.next;
}
return x;
}
index == 0 이면
first = node.next 삭제하는 노드의 다음 노드를 first가 가리키도록 한다.
prev.next = node.next; : 삭제하는 prev 노드가 삭제하는 노드가 가리키는 노드를 가리키도록 수정한다.