diff --git a/ub08/code/AddSet.java b/ub08/code/AddSet.java
new file mode 100755
index 0000000000000000000000000000000000000000..5462ce48026998b2cb0e8d8a9cf833b7d78c25c7
--- /dev/null
+++ b/ub08/code/AddSet.java
@@ -0,0 +1,43 @@
+/**
+ * @param <E> Element type.
+ * Simple functional set adding an element to another simple functional set.
+ */
+public class AddSet<E> extends SimpleFunctionalSet<E> {
+
+    /**
+     * The element to add.
+     */
+    private final E element;
+
+    /**
+     * @param elem The element to add.
+     * @param s The remaining set.
+     */
+    public AddSet(E elem, SimpleFunctionalSet<E> s) {
+        super(s);
+        this.element = elem;
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        if (this.element == null) {
+            if (o == null) {
+                return true;
+            } else {
+                return this.getRemainingSet().contains(o);
+            }
+        } else if (this.element.equals(o)) {
+            return true;
+        } else {
+            return this.getRemainingSet().contains(o);
+        }
+    }
+
+    /**
+     * @return The element to add.
+     */
+    public E getElement() {
+        return this.element;
+    }
+
+}
diff --git a/ub08/code/EmptySet.java b/ub08/code/EmptySet.java
new file mode 100755
index 0000000000000000000000000000000000000000..b9155b8e1555d09cf19dd93705c65c9efa04e92b
--- /dev/null
+++ b/ub08/code/EmptySet.java
@@ -0,0 +1,19 @@
+/**
+ * @param <E> Element type.
+ * Simple functional set containing no element.
+ */
+public class EmptySet<E> extends SimpleFunctionalSet<E> {
+
+    /**
+     * Creates an empty simple functional set.
+     */
+    public EmptySet() {
+        super(null);
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        return false;
+    }
+
+}
diff --git a/ub08/code/FunctionalSet.java b/ub08/code/FunctionalSet.java
new file mode 100755
index 0000000000000000000000000000000000000000..c52bcaeb0531f16aed8b37fe9a122eef9289fe79
--- /dev/null
+++ b/ub08/code/FunctionalSet.java
@@ -0,0 +1,203 @@
+import java.util.*;
+
+/**
+ * Functional data structure for a set.
+ * @param <E> Element type.
+ */
+public class FunctionalSet<E> implements Set<E> {
+
+    /**
+     * The head of the list of operations representing the set.
+     */
+    private SimpleFunctionalSet<E> head;
+
+    public String toString() {
+        String res = "{";
+        Iterator<E> it = iterator();
+        while (it.hasNext()) {
+            res = res + it.next();
+            if (it.hasNext()) {
+                res = res + ", ";
+            }
+        }
+        return res + "}";
+    }
+
+    public E min(Comparator<E> comp) throws MinimumOfEmptySetException {
+        if (isEmpty()) {
+            throw new MinimumOfEmptySetException();
+        } else {
+            E res = null;
+            for (E e: this) {
+                if (res == null || comp.compare(e, res) < 0) {
+                    res = e;
+                }
+            }
+            return res;
+        }
+    }
+
+    /**
+     * Creates an empty functional set.
+     */
+    public FunctionalSet() {
+        this.head = new EmptySet<E>();
+    }
+
+    @Override
+    public boolean add(E e) {
+        if (this.contains(e)) {
+            return false;
+        } else {
+            this.head = new AddSet<E>(e, this.head);
+            return true;
+        }
+    }
+
+    @Override
+    public boolean addAll(Collection<? extends E> c) {
+        boolean res = false;
+        for (E elem : c) {
+            res |= this.add(elem);
+        }
+        return res;
+    }
+
+    @Override
+    public void clear() {
+        this.head = new EmptySet<E>();
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        return this.head.contains(o);
+    }
+
+    @Override
+    public boolean containsAll(Collection<?> c) {
+        for (Object o : c) {
+            if (!this.contains(o)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        } else if (o == null || o.getClass() != this.getClass()) {
+            return false;
+        } else {
+            FunctionalSet<?> set = (FunctionalSet<?>)o;
+            return this.containsAll(set) && set.containsAll(this);
+        }
+    }
+
+    @Override
+    public int hashCode() {
+        int res = 5;
+        final int prime = 7;
+        for (E elem : this) {
+            res += prime * elem.hashCode();
+        }
+        return res;
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return this.size() == 0;
+    }
+
+    @Override
+    public Iterator<E> iterator() {
+        return new FunctionalSetIterator<E>(this, this.head);
+    }
+
+    @Override
+    public boolean remove(Object o) {
+        if (this.contains(o)) {
+            this.head = new RemoveSet<E>(o, this.head);
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public boolean removeAll(Collection<?> c) {
+        boolean res = false;
+        for (Object o : c) {
+            res |= this.remove(o);
+        }
+        return res;
+    }
+
+    @Override
+    public boolean retainAll(Collection<?> c) {
+        List<E> store = new ArrayList<E>();
+        boolean change = false;
+        for (E elem : this) {
+            if (c.contains(elem)) {
+                store.add(elem);
+            } else {
+                change = true;
+            }
+        }
+        if (change) {
+            this.clear();
+            for (E elem : store) {
+                this.add(elem);
+            }
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    @Override
+    public int size() {
+        int res = 0;
+        for (Iterator<E> it = this.iterator(); it.hasNext(); it.next()) {
+            res++;
+        }
+        return res;
+    }
+
+    @Override
+    public Object[] toArray() {
+        Object[] res = new Object[this.size()];
+        int i = 0;
+        for (E elem : this) {
+            res[i] = elem;
+            i++;
+        }
+        return res;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T>T[] toArray(T[] a) {
+        final int size = this.size();
+        final T[] res;
+        if (a.length < size) {
+            res = Arrays.copyOf(a, size);
+        } else {
+            res = a;
+        }
+        int i = 0;
+        for (E elem : this) {
+            try {
+                res[i] = (T)elem;
+            } catch (ClassCastException e) {
+                throw new ArrayStoreException(
+                    "Element " + elem + " cannot be cast to type of specified array!"
+                );
+            }
+            i++;
+        }
+        return res;
+    }
+
+}
diff --git a/ub08/code/FunctionalSetIterator.java b/ub08/code/FunctionalSetIterator.java
new file mode 100755
index 0000000000000000000000000000000000000000..3ed6e0d1f6be3a3be1c4abb9b9c5b5c4cf89bd61
--- /dev/null
+++ b/ub08/code/FunctionalSetIterator.java
@@ -0,0 +1,80 @@
+import java.util.*;
+
+/**
+ * @param <E> Element type.
+ * Iterator through a functional set.
+ */
+public class FunctionalSetIterator<E> implements Iterator<E> {
+
+    private SimpleFunctionalSet<E> current;
+
+    private E recentElem;
+
+    private boolean removable;
+
+    private final FunctionalSet<E> set;
+
+    private final Set<Object> used;
+
+    public FunctionalSetIterator(
+        FunctionalSet<E> functionalSet,
+        SimpleFunctionalSet<E> head)
+    {
+        this.current = head;
+        this.recentElem = null;
+        this.removable = false;
+        this.set = functionalSet;
+        this.used = new FunctionalSet<Object>();
+        this.forwardToNextUnusedSet();
+    }
+
+    @Override
+    public boolean hasNext() {
+        return !(this.current instanceof EmptySet);
+    }
+
+    @Override
+    public E next() {
+        if (this.hasNext()) {
+            E elem = ((AddSet<E>) this.current).getElement();
+            this.used.add(elem);
+            this.recentElem = elem;
+            this.removable = true;
+            this.current = this.current.getRemainingSet();
+            this.forwardToNextUnusedSet();
+            return elem;
+        } else {
+            throw new NoSuchElementException();
+        }
+    }
+
+    @Override
+    public void remove() {
+        if (this.removable) {
+            this.set.remove(this.recentElem);
+            this.removable = false;
+        } else {
+            throw new IllegalStateException(
+                "The next method has not been called before this remove operation!");
+        }
+    }
+
+    
+    private void forwardToNextUnusedSet() {
+        boolean loop = true;
+        while (loop) {
+            loop = false;
+            while (this.current instanceof RemoveSet) {
+                this.used.add(((RemoveSet<E>) this.current).getObject());
+                this.current = this.current.getRemainingSet();
+            }
+            if (this.current instanceof AddSet
+                && this.used.contains(((AddSet<E>) this.current).getElement()))
+            {
+                loop = true;
+                this.current = this.current.getRemainingSet();
+            }
+        }
+    }
+
+}
diff --git a/ub08/code/Main.java b/ub08/code/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..f1522e8011c0186d7a56d23d5efa90d299e76ff2
--- /dev/null
+++ b/ub08/code/Main.java
@@ -0,0 +1,34 @@
+import java.util.*;
+
+public class Main {
+    public static void main(String[] args) {
+        FunctionalSet<Integer> s = new FunctionalSet<>();
+        String line;
+        do {
+            line = SimpleIO.getString("Enter 'add i', 'remove i', 'min', or 'exit'!");
+            String[] words = line.split(" ");
+            try {
+                switch (words[0]) {
+                case "exit": break;
+                case "add":
+                    s.add(Integer.parseInt(words[1]));
+                    System.out.println(s);
+                    break;
+                case "remove":
+                    s.remove(Integer.parseInt(words[1]));
+                    System.out.println(s);
+                    break;
+                case "min":
+                    System.out.println(s.min(Comparator.<Integer>naturalOrder()));
+                    break;
+                default:
+                    System.out.println("Unknown command.");
+                }
+            } catch (MinimumOfEmptySetException e) {
+                System.out.println("The minimum of the empty set is not defined!");
+            } catch (NumberFormatException e) {
+                System.out.println("Failed to parse the number to add/remove.");
+            }
+        } while (!"exit".equals(line));
+    }
+}
diff --git a/ub08/code/MinimumOfEmptySetException.java b/ub08/code/MinimumOfEmptySetException.java
new file mode 100644
index 0000000000000000000000000000000000000000..6d1bce5c24ad943c6cc0b77de3177f9746157e12
--- /dev/null
+++ b/ub08/code/MinimumOfEmptySetException.java
@@ -0,0 +1 @@
+public class MinimumOfEmptySetException extends java.lang.RuntimeException{}
diff --git a/ub08/code/RemoveSet.java b/ub08/code/RemoveSet.java
new file mode 100755
index 0000000000000000000000000000000000000000..64f8fb414d81cd9eefc89ce411f4060cea3f7928
--- /dev/null
+++ b/ub08/code/RemoveSet.java
@@ -0,0 +1,43 @@
+/**
+ * @param <E> Element type.
+ * Simple set removing an object from another simple set.
+ */
+public class RemoveSet<E> extends SimpleFunctionalSet<E> {
+
+    /**
+     * The object to remove.
+     */
+    private final Object obj;
+
+    /**
+     * @param o The object to remove.
+     * @param s The remaining set.
+     */
+    public RemoveSet(Object o, SimpleFunctionalSet<E> s) {
+        super(s);
+        this.obj = o;
+    }
+
+    @Override
+    public boolean contains(Object o) {
+        if (this.obj == null) {
+            if (o == null) {
+                return false;
+            } else {
+                return this.getRemainingSet().contains(o);
+            }
+        } else if (this.obj.equals(o)) {
+            return false;
+        } else {
+            return this.getRemainingSet().contains(o);
+        }
+    }
+
+    /**
+     * @return The object to remove.
+     */
+    public Object getObject() {
+        return this.obj;
+    }
+
+}
diff --git a/ub08/code/SimpleFunctionalSet.java b/ub08/code/SimpleFunctionalSet.java
new file mode 100755
index 0000000000000000000000000000000000000000..0a11a6d2c870398cc5713877b395b834ccf6f290
--- /dev/null
+++ b/ub08/code/SimpleFunctionalSet.java
@@ -0,0 +1,37 @@
+/**
+ * @param <E> Element type.
+ * Abstract class for simple functional sets just offering a characteristic function realized by the
+ * contains method.
+ */
+public abstract class SimpleFunctionalSet<E> {
+
+    /**
+     * The remaining set.
+     */
+    private final SimpleFunctionalSet<E> set;
+
+    /**
+     * @param s The remaining set.
+     */
+    public SimpleFunctionalSet(SimpleFunctionalSet<E> s) {
+        this.set = s;
+    }
+
+    /**
+     * Returns <tt>true</tt> if this set contains the specified element.
+     * More formally, contains(o) returns <tt>true</tt> if and only if this set
+     * contains an element <tt>e</tt> such that
+     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;e.equals(o))</tt>.
+     * @param o Element whose presence in this set is to be tested.
+     * @return <tt>true</tt> if this set contains the specified element.
+     */
+    public abstract boolean contains(Object o);
+
+    /**
+     * @return The remaining set.
+     */
+    public SimpleFunctionalSet<E> getRemainingSet() {
+        return this.set;
+    }
+
+}
diff --git a/ub08/code/SimpleIO.java b/ub08/code/SimpleIO.java
new file mode 100644
index 0000000000000000000000000000000000000000..aab616cf7c226e750b8281ea0661105e7801820e
--- /dev/null
+++ b/ub08/code/SimpleIO.java
@@ -0,0 +1,254 @@
+
+
+import java.awt.GraphicsEnvironment;
+import java.util.Scanner;
+
+import javax.swing.JOptionPane;
+
+/**
+ * Class SimpleIO - class for input of simple input types
+ * via simple dialog box (or if headless System.in use) 
+ * and output of strings (vie dialog box or System.out)
+ */
+
+public class SimpleIO
+{
+    //Running without display support?
+    private static final boolean HEADLESS = GraphicsEnvironment.isHeadless();
+    
+    /**
+     * Prompting the user for input (If Headless, will be prompted with System.in and System.out)
+     * @param title Title of the input
+     * @param messages Message that will be shown to the user
+     * @param options Optional: Give the user options
+     * @param initialOption Optional: The initial option
+     * @return The input string or the index of the selected option
+     */
+    private static String getInputString(String title, Object messages[], 
+            Object[] options, Object initialOption){
+        return HEADLESS ? headlessImpl(title, messages, options, initialOption) : 
+            displayImpl(title, messages, options, initialOption);
+    }
+    
+    /**
+     * Prompting the user for input (If Headless, will be prompted with System.in and System.out)
+     * @param title Title of the input
+     * @param messages Message that will shown
+     * @return The inputstring
+     */
+    private static String getInputString(String title, Object messages[]){
+        return getInputString(title, messages, null, null);
+    }
+    
+    private static String headlessImpl(String title, Object messages[], 
+            Object[] options, Object initialOption){
+        @SuppressWarnings("resource")//System.in should not be closed
+        Scanner scanner = new Scanner(System.in);
+        
+        System.out.println(title);
+        
+        for(Object o : messages)
+            System.out.println(o.toString());
+        
+        if(options != null){
+            System.out.print("Choose one: |");
+            
+            for(Object option : options){
+                if(option == initialOption){
+                    System.out.print(" " + option.toString() + " (INITIAL) |");
+                }
+                else{
+                    System.out.print(" " + option.toString() + " |");
+                }
+            }
+            
+            System.out.println("");
+        }
+        
+        String result = scanner.nextLine();
+        
+        if(options != null){
+            for(int i = 0; i < options.length; i++){
+                if(options[i].toString().equals(result))
+                    return i + "";
+            }
+            
+            return null;
+        }
+        
+        
+        return result;
+    }
+    
+    /**
+     * Prompting the user with a gui
+     * @param title The title from the frame
+     * @param messages The message the user will be shown
+     * @param options Optional: Give the user options
+     * @param initialOption Optional: The initial option
+     * @return The inputstring or the index of the option if given
+     */
+    private static String displayImpl(String title, Object messages[], 
+            Object[] options, Object initialOption){
+        if(options == null){
+            return JOptionPane.showInputDialog(null, messages, title, JOptionPane.QUESTION_MESSAGE);
+        }
+        else{
+            return "" + JOptionPane.showOptionDialog(null, messages, title, 
+                    JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, 
+                    null, options, initialOption);
+        }
+    }
+    
+    /**
+     * Getting information from the user and returning it
+     * @param type The type of information
+     * @param prompt The question prompted to the user
+     * @return the information as Object (It can safely casted to the given type)
+     */
+    private static Object getInputLine(Type type, String prompt){
+        Object result = null;
+        Object[] commentArray = {prompt, "", ""};
+        
+        while(result == null){
+            String response;
+            
+            if(type == Type.Boolean){
+                response = getInputString(type.getDescription() + " eingeben", commentArray, 
+                        new String[]{"True", "False"}, "True");
+            }
+            else{
+                response = getInputString(type.getDescription() + " eingeben", commentArray);
+            }
+            
+            
+            if(response != null){
+                try{
+                    switch (type) {
+                    case String:{
+                        result = response;
+                        break;
+                    }
+                    case Boolean:{
+                        result = response.equals("0");
+                        break;
+                    }
+                    case Int:{
+                        result = Integer.parseInt(response);
+                        break;
+                    }
+                    case Char:{
+                        if(response.length() == 1){
+                            result = response.charAt(0);
+                        }
+                        
+                        break;
+                    }
+                    case Float:{
+                        result = Float.parseFloat(response);
+                        break;
+                    }
+                    case Double:{
+                        result = Double.parseDouble(response);
+                        break;
+                    }
+                    default:
+                        throw new IllegalStateException("Type incorrect");
+                    }  
+                } 
+                catch(NumberFormatException exception){
+                    result = null;
+                }
+            }
+            
+            if(result == null){
+                commentArray[1] = "Invalid input: " + response;
+                commentArray[2] = "Enter a valid " + type.getDescription();
+            }
+        }
+        
+        return result;
+    }
+    
+    /**
+     ** String input from the user via a simple dialog.
+     ** @param prompt the message string to be displayed inside dialog    
+     ** @return String input from the user.
+     **/
+    public static String getString(String prompt){
+        return (String) getInputLine(Type.String, prompt);
+    }
+
+    /**
+     ** char input from the user via a simple dialog.
+     ** @param prompt the message string to be displayed inside dialog  
+     ** @return char input from the user.
+     **/
+    public static char getChar(String prompt){
+        return (char) getInputLine(Type.Char, prompt);
+    }
+
+    /**
+     ** boolean selection from the user via a simple dialog.
+     ** @param  prompt message to appear in dialog
+     ** @return boolean selection from the user
+     **/
+    public static boolean getBoolean(String prompt){
+        return (boolean) getInputLine(Type.Boolean, prompt);
+    }
+
+
+   /**
+    ** returns integer input from the user via a simple dialog.
+    ** @param prompt the message string to be displayed inside dialog
+    ** @return the input integer
+    **/
+    public static int getInt(String prompt){
+        return (int) getInputLine(Type.Int, prompt);
+    }
+
+
+   /**
+    ** returns a float input from the user via a simple dialog.
+    ** @param prompt the message string to be displayed inside dialog
+    ** @return the input float
+    **/
+    public static float getFloat(String prompt){
+        return (float) getInputLine(Type.Float, prompt);
+    }
+
+   /**
+    ** returns a double input from the user via a simple dialog.
+    ** @param prompt the message string to be displayed inside dialog
+    ** @return the input double
+    **/
+    public static double getDouble(String prompt){
+        return (double) getInputLine(Type.Double, prompt);
+    }
+    
+    /**
+     * Defines the type from the user-question
+     */
+    private enum Type{
+        String("String"), Char("Char"), Int("int"), 
+        Boolean("Boolean"), Float("Float"), Double("Double");
+        
+        private String description;
+        
+        private Type(String input){
+            this.description = input;
+        }
+        
+        public String getDescription(){
+            return description;
+        }
+    }
+
+    /** prints the string "content" in a window with the title "title"
+     ** @param content the string to be displayed
+     ** @param title the title of the display window
+     **/
+    public static void output (String content, String title) {
+        JOptionPane.showMessageDialog (null,content,title,JOptionPane.PLAIN_MESSAGE); 
+    }
+}