import java.util.function.Consumer;

public class LinkedList<A> {
	A head;
	LinkedList<A> tail;
	
	public LinkedList(A head, LinkedList<A> tail) {
		this.head = head;
		this.tail = tail;
	}
	public LinkedList() {
		this(null,null);
	}
	public LinkedList(A... as) {
		head = null;
		tail = null;
		for (int i = as.length-1; i >=0 ; i--) {
			tail = new LinkedList<A>(head, tail);
			head = as[i];
		}
	}
	
	boolean isEmpty() {
		return head==null && tail == null;
	}
	int length(){
		if (isEmpty()) return 0;
		return 1+tail.length();
	}
	int lengthIterative(){
		int result = 0;
		for (var it=this; !it.isEmpty(); it = it.tail) {
			result++;
		}
		return result;
	}
	
	boolean contains(A k) {
		if (isEmpty()) return false;
		return head.equals(k)||tail.contains(k);
	}

	
	void forEach(Consumer<A> aktion) {
		if (isEmpty()) return;
		aktion.accept(head);
		tail.forEach(aktion);
	}

	void forEachIterative(Consumer<A> aktion) {
		for (var it=this; !it.isEmpty(); it = it.tail) {
			var elem = it.head;
			aktion.accept(elem);
		}
	
	}

	
	public static void main(String[] args) {
		var xs = new LinkedList<Keks>();
		xs = new LinkedList<>(new Keks('e'), xs);
		xs = new LinkedList<>(new Keks('s'), xs);
		xs = new LinkedList<>(new Keks('o'), xs);
		xs = new LinkedList<>(new Keks('o'), xs);
		System.out.println(xs.length());
		System.out.println(xs.contains(new Keks('s')));
		System.out.println(xs.contains(new Keks('x')));
		xs.forEach((Keks k) -> k.c = (char)(k.c+1));
		
		xs.forEach((Keks k) -> System.out.println(k.c));
		var ys = new LinkedList<String>();
		ys = new LinkedList<String>("Gurkensalat", ys);
		ys = new LinkedList<String>("keinen", ys);
		ys = new LinkedList<String>("frisst", ys);
		ys = new LinkedList<String>("Pferd", ys);
		ys = new LinkedList<String>("das", ys);
		System.out.println(ys.length());
		System.out.println(ys.contains("Pferd"));
		System.out.println(ys.contains("Sonne"));
		
		ys.forEach( k -> System.out.println(k.toUpperCase()));
		var is = new LinkedList<Integer>(1,2,3,4,5,6,7,8,9,10);
		System.out.println(is.length());
		System.out.println(is.lengthIterative());
		is.forEachIterative(i->System.out.println(i*i));

	}
	
}
