OOPの理解のため、
抽象クラス、インターフェース、ジェネリクスを使用して、 双方向連結リスト(GenericLinkedList)と動的配列(GenericArrayList)のデータ構造を作成しました。
※実装の詳細については、後日追記します。
import java.lang.StringBuilder;
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
interface Queue<E> {
public abstract E peekFront(); // リストの先頭にある要素を返します。
public abstract E popFront(); // リストの先頭の要素を削除し、削除した要素を返します。
public abstract void pushBack(E data); // リストの末尾に要素を追加します。
}
interface Stack<E> {
public abstract E peekBack(); // リストの末尾にある要素を返します。
public abstract E popBack(); // リストの末尾の要素を削除し、削除した要素を返します。
public abstract void pushBack(E data); // リストの末尾に要素を追加します。
}
interface Deque<E> extends Stack<E>, Queue<E>{
public abstract void pushFront(E data); // リストの先頭に要素を追加します。
}
abstract class GenericAbstractList<E> implements Deque<E>{
private E[] initialList;
// 汎用的なリストを使ってAbstractListを開始することも、空のリストを使って開始することもできます。
public GenericAbstractList(){}
public GenericAbstractList(E[] arr){
this.initialList = arr;
}
public E[] getOriginalList(){
return initialList;
}
// GenericAbstractListが実装しなければならないメソッド
public abstract E get(int index);
public abstract void add(E element);
public abstract void add(E[] elements);
public abstract E pop();
public abstract void addAt(int index, E element);
public abstract void addAt(int index, E[] elements);
public abstract E removeAt(int index);
public abstract void removeAllAt(int start);
public abstract void removeAllAt(int start, int end);
public abstract GenericAbstractList<E> subList(int start);
public abstract GenericAbstractList<E> subList(int start, int end);
}
class Node<E>{
public E data;
public Node<E> prev;
public Node<E> next;
public Node(E data){
this.data = data;
}
}
class GenericLinkedList<E> extends GenericAbstractList<E>{
private Node<E> head;
private Node<E> tail;
public GenericLinkedList(){
super();
}
public String toString(){
StringBuilder str = new StringBuilder("[");
Node<E> iterator = this.head;
while(iterator != null){
str.append(iterator.data + ", ");
iterator = iterator.next;
}
str.append("]");
return str.toString();
}
public E peekFront(){
if(this.head == null)return null;
return this.head.data;
}
public E popFront(){
if(this.head == null)return null;
Node<E> temp = this.head;
this.head = this.head.next;
if(this.head != null)this.head.prev = null;
else this.tail = null;
return temp.data;
}
public void pushBack(E data){
Node<E> node = new Node<E>(data);
if(this.peekBack() == null){
this.head = node;
this.tail = this.head;
}else{
node.prev = this.tail;
this.tail.next = node;
this.tail = this.tail.next;
}
}
public E peekBack(){
if(this.tail == null)return this.peekFront();
return this.tail.data;
}
public E popBack(){
if(this.tail == null)return null;
Node<E> temp = this.tail;
this.tail = this.tail.prev;
if(this.tail != null)this.tail.next = null;
else this.head = null;
return temp.data;
}
public void pushFront(E data){
Node<E> node = new Node<E>(data);
if(this.peekFront() == null){
this.head = node;
this.tail = this.head;
}else{
node.next = this.head;
this.head.prev = node;
this.head = this.head.prev;
}
}
public Node<E> at(int index){
if(index < 0)return null;
Node<E> iterator = this.head;
for(int i = 0; i < index; i++){
iterator = iterator.next;
if(iterator == null)return null;
}
return iterator;
}
public int size(){
if(this.head == null)return 0;
int size = 0;
Node<E> iterator = this.head;
while(iterator != null){
size++;
iterator = iterator.next;
}
return size;
}
// GenericAbstractListが実装しなければならないメソッド
public E get(int index){
Node<E> found = this.at(index);
if(found == null)return null;
return found.data;
}
public void add(E element){
this.pushBack(element);
}
public void add(E[] elements){
for(int i = 0; i < elements.length; i++){
this.pushBack(elements[i]);
}
}
public E pop(){
return this.popBack();
}
public void addAt(int index, E element){
if(index < 0)return;
if(index == this.size()){
this.pushBack(element);
return;
}
Node<E> targetNode = this.at(index);
if(targetNode == this.head){
this.pushFront(element);
return;
}
Node<E> node = new Node<E>(element);
node.prev = targetNode.prev;
node.next = targetNode;
node.prev.next = node;
targetNode.prev = node;
}
public void addAt(int index, E[] elements){
if(index < 0)return;
if(index == this.size()){
this.add(elements);
return;
}
Node<E> targetNode = this.at(index);
if(targetNode == this.head){
for(int i = elements.length-1; i >= 0; i++){
this.pushFront(elements[i]);
}
return;
}
for(int i = 0; i < elements.length; i++){
Node<E> node = new Node<E>(elements[i]);
node.prev = targetNode.prev;
node.next = targetNode;
node.prev.next = node;
targetNode.prev = node;
}
}
public E removeAt(int index){
Node<E> deleteNode = this.at(index);
if(deleteNode == null)return null;
if(deleteNode == this.head)this.popFront();
else if(deleteNode == this.tail)this.popBack();
else{
deleteNode.prev.next = deleteNode.next;
deleteNode.next.prev = deleteNode.prev;
}
return deleteNode.data;
}
public void removeAllAt(int start){
Node<E> deleteNode = this.at(start);
if(deleteNode == null)return;
this.tail = deleteNode.prev;
if(this.tail != null)this.tail.next = null;
else this.head = null;
}
public void removeAllAt(int start, int end){
Node<E> startNode = this.at(start);
Node<E> endNode = this.at(end);
if(startNode == null)return;
else if(endNode == null){
this.tail = startNode.prev;
if(this.tail != null)this.tail.next = null;
else this.head = null;
}else{
startNode.prev.next = endNode;
endNode.prev = startNode.prev;
}
}
public GenericAbstractList<E> subList(int start){
Node<E> iterator = this.at(start);
GenericAbstractList<E> deepCopy = new GenericLinkedList<E>();
while(iterator != null){
deepCopy.pushBack(iterator.data);
iterator = iterator.next;
}
return deepCopy;
}
public GenericAbstractList<E> subList(int start, int end){
Node<E> iterator = this.at(start);
Node<E> endNode = this.at(end);
GenericAbstractList<E> deepCopy = new GenericLinkedList<E>();
while(iterator != null && iterator != endNode){
deepCopy.pushBack(iterator.data);
iterator = iterator.next;
}
return deepCopy;
}
}
class GenericArrayList<E> extends GenericAbstractList<E>{
private ArrayList<E> arraylist;
public GenericArrayList(){
super();
this.arraylist = new ArrayList<E>();
}
public GenericArrayList(E[] arr){
super(arr);
this.arraylist = new ArrayList<E>(arr.length);
Arrays.stream(arr).forEach(x -> this.arraylist.add(x));
}
public String toString(){
StringBuilder str = new StringBuilder("[");
for(int i = 0; i < this.arraylist.size(); i++){
str.append(this.arraylist.get(i) + ", ");
}
str.append("]");
return str.toString();
}
public E peekFront(){
return this.arraylist.get(0);
}
public E popFront(){
E data = this.arraylist.get(0);
this.arraylist.remove(0);
return data;
}
public void pushBack(E data){
this.arraylist.add(data);
}
public E peekBack(){
return this.arraylist.get(this.arraylist.size()-1);
}
public E popBack(){
E data = this.arraylist.get(this.arraylist.size()-1);
this.arraylist.remove(this.arraylist.size()-1);
return data;
}
public void pushFront(E data){
this.arraylist.set(0, data);
}
// GenericAbstractListが実装しなければならないメソッド
public E get(int index){
return this.arraylist.get(index);
}
public void add(E element){
this.pushBack(element);
}
public void add(E[] elements){
ArrayList<E> curr = this.arraylist;
this.arraylist = new ArrayList<E>(curr.size() + elements.length);
this.arraylist.addAll(curr);
for(int i = 0; i < elements.length; i++){
this.arraylist.add(elements[i]);
}
}
public E pop(){
return this.popBack();
}
public void addAt(int index, E element){
ArrayList<E> curr = this.arraylist;
this.arraylist = new ArrayList<E>(curr.size() + 1);
for(int i = 0; i < this.arraylist.size(); i++){
if(i == index){
this.arraylist.add(element);
}
this.arraylist.add(curr.get(i));
}
}
public void addAt(int index, E[] elements){
ArrayList<E> curr = this.arraylist;
this.arraylist = new ArrayList<E>(curr.size() + elements.length);
for(int i = 0; i < this.arraylist.size(); i++){
if(i == index){
for(int j = 0; i < elements.length; i++){
this.arraylist.add(elements[i]);
}
}
this.arraylist.add(curr.get(i));
}
}
public E removeAt(int index){
E data = this.arraylist.get(index);
this.arraylist.set(index, null);
return data;
}
public void removeAllAt(int start){
for(int i = start; i < this.arraylist.size(); i++){
this.arraylist.set(i, null);
}
}
public void removeAllAt(int start, int end){
for(int i = start; i < end; i++){
this.arraylist.set(i, null);
}
}
public GenericAbstractList<E> subList(int start){
GenericAbstractList<E> list = new GenericArrayList<E>();
for(int i = start; i < this.arraylist.size(); i++){
list.add(this.arraylist.get(i));
}
return list;
}
public GenericAbstractList<E> subList(int start, int end){
GenericAbstractList<E> list = new GenericArrayList<E>();
for(int i = start; i < end; i++){
list.add(this.arraylist.get(i));
}
return list;
}
}
class Main{
public static void main(String[] args){
GenericLinkedList<Integer> integerLinkedList = new GenericLinkedList<Integer>();
integerLinkedList.add(1);
integerLinkedList.add(2);
integerLinkedList.add(3);
integerLinkedList.add(4);
integerLinkedList.add(5);
integerLinkedList.add(6);
integerLinkedList.add(7);
System.out.println(integerLinkedList);
System.out.println(integerLinkedList.peekFront());
System.out.println(integerLinkedList.peekBack());
System.out.println(integerLinkedList.popFront());
System.out.println(integerLinkedList.popBack());
integerLinkedList.pushFront(8);
System.out.println(integerLinkedList);
System.out.println(integerLinkedList.subList(2, 4));
integerLinkedList.removeAllAt(1);
System.out.println(integerLinkedList);
GenericArrayList<Character> characterArrayList = new GenericArrayList<Character>();
characterArrayList.add('a');
characterArrayList.add('b');
characterArrayList.add('c');
characterArrayList.add('d');
characterArrayList.add('e');
characterArrayList.add('f');
characterArrayList.add('g');
System.out.println(characterArrayList);
System.out.println(characterArrayList.peekFront());
System.out.println(characterArrayList.peekBack());
System.out.println(characterArrayList.popFront());
System.out.println(characterArrayList.popBack());
characterArrayList.pushFront('h');
System.out.println(characterArrayList.subList(2, 4));
characterArrayList.removeAllAt(2, 4);
System.out.println(characterArrayList);
}
}