diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..65f75cfdb0031b64cdbf9726168ae53ff0222666
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,9 @@
+.DS_Store
+.gradle
+/build/
+/out/
+gradle-app.setting
+!gradle-wrapper.jar
+.gradletasknamecache
+.idea/
+*.iml
diff --git a/LICENSE b/LICENSE
index e7dccd4e746475ebb0b688ea57d72e4148c2fcb8..ed3a58dc8971785b81f4ad71d31109737fb8950d 100644
--- a/LICENSE
+++ b/LICENSE
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
+SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
index 98bc09b9e8744567806a9eaf1a62cf346141e4ad..0274a1af932acb66cc198f04993815b24328d729 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,5 @@
-# 05-generic-bounds
\ No newline at end of file
+# 05-generic-bounds
+
+* PECS `map`
+* `Plant`, `Flower`, `Shrub`, `PlantBed`
+* `splitByColor`
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..18dc052510e192ffd1d4242a853479f954f234c3
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,36 @@
+group 'de.fhro.inf.prg3'
+version '1.0-SNAPSHOT'
+
+apply plugin: 'java'
+apply plugin: 'org.junit.platform.gradle.plugin'
+
+sourceCompatibility = 1.8
+
+buildscript {
+    repositories {
+        mavenCentral()
+    }
+    dependencies {
+        classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0'
+    }
+}
+
+repositories {
+    mavenCentral()
+}
+
+dependencies {
+    testCompile("org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}")
+    testRuntime("org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}")
+    testRuntime("org.junit.platform:junit-platform-launcher:${junitPlatformVersion}")
+    compile("org.apache.logging.log4j:log4j-core:${log4jVersion}")
+    runtime("org.apache.logging.log4j:log4j-jul:${log4jVersion}")
+    compile "org.apache.commons:commons-lang3:$commons_lang3_version"
+}
+
+junitPlatform {
+    logManager 'org.apache.logging.log4j.jul.LogManager'
+    reportsDir file('build/test-results/junit-platform')
+}
+
+
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000000000000000000000000000000000000..44ff5c90605fbeba370dc90b79256f8d8e892686
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,4 @@
+junitPlatformVersion = 1.0.0
+junitJupiterVersion = 5.0.0
+log4jVersion = 2.9.0
+commons_lang3_version=3.6
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000000000000000000000000000000000000..ed88a042a287c140a32e1639edfc91b2a233da8c
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..74bb77845e0be3bde9aca603aedfa16c669ded8b
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,5 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.2.1-bin.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000000000000000000000000000000000000..cccdd3d517fc5249beaefa600691cf150f2fa3e6
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+##  Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+    ls=`ls -ld "$PRG"`
+    link=`expr "$ls" : '.*-> \(.*\)$'`
+    if expr "$link" : '/.*' > /dev/null; then
+        PRG="$link"
+    else
+        PRG=`dirname "$PRG"`"/$link"
+    fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+    echo "$*"
+}
+
+die () {
+    echo
+    echo "$*"
+    echo
+    exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+  CYGWIN* )
+    cygwin=true
+    ;;
+  Darwin* )
+    darwin=true
+    ;;
+  MINGW* )
+    msys=true
+    ;;
+  NONSTOP* )
+    nonstop=true
+    ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+        # IBM's JDK on AIX uses strange locations for the executables
+        JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+        JAVACMD="$JAVA_HOME/bin/java"
+    fi
+    if [ ! -x "$JAVACMD" ] ; then
+        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+    fi
+else
+    JAVACMD="java"
+    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+    MAX_FD_LIMIT=`ulimit -H -n`
+    if [ $? -eq 0 ] ; then
+        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+            MAX_FD="$MAX_FD_LIMIT"
+        fi
+        ulimit -n $MAX_FD
+        if [ $? -ne 0 ] ; then
+            warn "Could not set maximum file descriptor limit: $MAX_FD"
+        fi
+    else
+        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+    fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+    JAVACMD=`cygpath --unix "$JAVACMD"`
+
+    # We build the pattern for arguments to be converted via cygpath
+    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+    SEP=""
+    for dir in $ROOTDIRSRAW ; do
+        ROOTDIRS="$ROOTDIRS$SEP$dir"
+        SEP="|"
+    done
+    OURCYGPATTERN="(^($ROOTDIRS))"
+    # Add a user-defined pattern to the cygpath arguments
+    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+    fi
+    # Now convert the arguments - kludge to limit ourselves to /bin/sh
+    i=0
+    for arg in "$@" ; do
+        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option
+
+        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
+            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+        else
+            eval `echo args$i`="\"$arg\""
+        fi
+        i=$((i+1))
+    done
+    case $i in
+        (0) set -- ;;
+        (1) set -- "$args0" ;;
+        (2) set -- "$args0" "$args1" ;;
+        (3) set -- "$args0" "$args1" "$args2" ;;
+        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+    esac
+fi
+
+# Escape application args
+save () {
+    for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+    echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+  cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000000000000000000000000000000000000..f9553162f122c71b34635112e717c3e733b5b212
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem  Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000000000000000000000000000000000000..8403dc3097c364b080e721ab2372fae65df31937
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,18 @@
+/*
+ * This settings file was generated by the Gradle 'init' task.
+ *
+ * The settings file is used to specify which projects to include in your build.
+ * In a single project build this file can be empty or even removed.
+ *
+ * Detailed information about configuring a multi-project build in Gradle can be found
+ * in the user guide at https://docs.gradle.org/4.2.1/userguide/multi_project_builds.html
+ */
+
+/*
+// To declare projects as part of a multi-project build use the 'include' method
+include 'shared'
+include 'api'
+include 'services:webservice'
+*/
+
+rootProject.name = '05-generic-bounds'
diff --git a/src/main/java/de/fhro/inf/prg3/a05/collections/SimpleFilter.java b/src/main/java/de/fhro/inf/prg3/a05/collections/SimpleFilter.java
new file mode 100644
index 0000000000000000000000000000000000000000..d7e0d4eeb0f9e20ff97156e7fd8a3b53ad404d07
--- /dev/null
+++ b/src/main/java/de/fhro/inf/prg3/a05/collections/SimpleFilter.java
@@ -0,0 +1,18 @@
+package de.fhro.inf.prg3.a05.collections;
+
+/**
+ * @author Peter Kurfer
+ * Created on 10/6/17.
+ */
+@FunctionalInterface
+public interface SimpleFilter<T> {
+
+	/**
+	 * Determines if a item matches a condition
+	 *
+	 * @param item Object to evaluate
+	 * @return true if the referenced object should be included.
+	 */
+	boolean include(T item);
+}
+
diff --git a/src/main/java/de/fhro/inf/prg3/a05/collections/SimpleList.java b/src/main/java/de/fhro/inf/prg3/a05/collections/SimpleList.java
new file mode 100644
index 0000000000000000000000000000000000000000..5c4d93e4dd07e1ca6ecf97c0c55c64fa3983287b
--- /dev/null
+++ b/src/main/java/de/fhro/inf/prg3/a05/collections/SimpleList.java
@@ -0,0 +1,90 @@
+package de.fhro.inf.prg3.a05.collections;
+
+import java.util.function.Function;
+
+/**
+ * A simple list containing just a few basic methods
+ * Inherits the Iterable interface to ease the handling (e.g. extended for-loop)
+ *
+ * @param <T> type of the items which will be saved in the list
+ */
+public interface SimpleList<T> extends Iterable<T> {
+
+	/**
+	 * Add a given object to the back of the list.
+	 *
+	 * @param o item to add
+	 */
+	void add(T o);
+
+	/**
+	 * @param clazz Class instance to solve the instantiation problem
+	 */
+	@SuppressWarnings("unchecked")
+	default void addDefault(Class<T> clazz) {
+		try {
+			/* better solution would be to use Google Guava to get a type token
+			and use this token to create a new instance
+			because we didn't include a reference to Guava this is the easiest way to create new instance of T */
+			this.add(clazz.newInstance());
+		} catch (InstantiationException | IllegalAccessException e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * @return current size of the list
+	 */
+	int size();
+
+	/**
+	 * Generate a new list using the given filter instance.
+	 *
+	 * @param filter SimpleFilter instance to determine which elements should be included
+	 * @return a new, filtered list
+	 */
+	@SuppressWarnings("unchecked")
+	default SimpleList<T> filter(SimpleFilter<T> filter) {
+		SimpleList<T> result;
+		try {
+			result = (SimpleList<T>) getClass().newInstance();
+		} catch (InstantiationException | IllegalAccessException e) {
+			result = new SimpleListImpl<>();
+		}
+
+		for (T o : this) {
+			if (filter.include(o)) {
+				result.add(o);
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * @param transform
+	 * @param <R>
+	 * @return
+	 */
+	@SuppressWarnings("unchecked")
+	default <R> SimpleList<R> map(Function<T, R> transform) {
+		SimpleList<R> result;
+		try {
+			result = (SimpleList<R>) getClass().newInstance();
+		} catch (InstantiationException | IllegalAccessException e) {
+			result = new SimpleListImpl<>();
+		}
+		for (T t : this) {
+			result.add(transform.apply(t));
+		}
+		return result;
+	}
+
+	/* Java 9
+	private <V> SimpleList<V> createNew(Class<SimpleList<V>> clazz){
+		try {
+			return clazz.getConstructor().newInstance()
+		} catch (Exception e) {
+			return new SimpleListImpl<>();
+		}
+	}*/
+}
diff --git a/src/main/java/de/fhro/inf/prg3/a05/collections/SimpleListImpl.java b/src/main/java/de/fhro/inf/prg3/a05/collections/SimpleListImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..ce5e786e197d3f8c2d96901e3e903705db36d47e
--- /dev/null
+++ b/src/main/java/de/fhro/inf/prg3/a05/collections/SimpleListImpl.java
@@ -0,0 +1,124 @@
+package de.fhro.inf.prg3.a05.collections;
+
+import java.util.Iterator;
+
+/**
+ * Default implementation of the SimpleList interface
+ *
+ * @author Peter Kurfer
+ * Created on 10/6/17.
+ */
+public class SimpleListImpl<T> implements SimpleList<T> {
+
+	private ListElement<T> head;
+	private int size;
+
+	/**
+	 * Default constructor
+	 */
+	public SimpleListImpl() {
+		head = null;
+	}
+
+	/**
+	 * Add an object to the end of the list
+	 *
+	 * @param item item to add
+	 */
+	@Override
+	public void add(T item) {
+		/* special case empty list */
+		if (head == null) {
+			head = new ListElement<>(item);
+		} else {
+			/* any other list length */
+			ListElement<T> current = head;
+			while (current.getNext() != null) {
+				current = current.getNext();
+			}
+			current.setNext(new ListElement<>(item));
+		}
+		size++;
+	}
+
+	/**
+	 * @return size of the list
+	 */
+	@Override
+	public int size() {
+		return size;
+	}
+
+	/**
+	 * Create a new iterator
+	 */
+	@Override
+	public Iterator<T> iterator() {
+		return new SimpleIterator();
+	}
+
+	/**
+	 * Helper class which implements the Iterator<TE> interface
+	 * Has to be non static because otherwise it could not access the head of the list
+	 */
+	private class SimpleIterator implements Iterator<T> {
+
+		private ListElement<T> current = head;
+
+		/**
+		 * @inheritDoc
+		 */
+		@Override
+		public boolean hasNext() {
+			return current != null;
+		}
+
+		/**
+		 * @inheritDoc
+		 */
+		@Override
+		public T next() {
+			T tmp = current.getItem();
+			current = current.getNext();
+			return tmp;
+		}
+	}
+
+	/**
+	 * Helper class for the linked list
+	 * can be static because the ListElement does not need to access the SimpleList instance
+	 */
+	private static class ListElement<T> {
+		private T item;
+		private ListElement<T> next;
+
+		ListElement(T item) {
+			this.item = item;
+			this.next = null;
+		}
+
+		/**
+		 * @return get object in the element
+		 */
+		public T getItem() {
+			return item;
+		}
+
+		/**
+		 * @return successor of the ListElement - may be NULL
+		 */
+		public ListElement<T> getNext() {
+			return next;
+		}
+
+		/**
+		 * Sets the successor of the ListElement
+		 *
+		 * @param next ListElement
+		 */
+		public void setNext(ListElement<T> next) {
+			this.next = next;
+		}
+	}
+
+}
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000000000000000000000000000000000..99d963ac06f0a6b14216ce4407d46f9eb6859a62
--- /dev/null
+++ b/src/main/resources/log4j2.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="WARN">
+    <Appenders>
+        <Console name="Console" target="SYSTEM_OUT">
+            <PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
+        </Console>
+    </Appenders>
+    <Loggers>
+        <Root level="all">
+            <AppenderRef ref="Console"/>
+        </Root>
+    </Loggers>
+</Configuration>
\ No newline at end of file
diff --git a/src/test/java/de/fhro/inf/prg3/a05/tests/collections/SimpleListTests.java b/src/test/java/de/fhro/inf/prg3/a05/tests/collections/SimpleListTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..0bf94c41c2e9551f7a1e616a65184e0d6e0b21ff
--- /dev/null
+++ b/src/test/java/de/fhro/inf/prg3/a05/tests/collections/SimpleListTests.java
@@ -0,0 +1,113 @@
+package de.fhro.inf.prg3.a05.tests.collections;
+
+import de.fhro.inf.prg3.a05.collections.SimpleFilter;
+import de.fhro.inf.prg3.a05.collections.SimpleList;
+import de.fhro.inf.prg3.a05.collections.SimpleListImpl;
+import de.fhro.inf.prg3.a05.tests.models.Person;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Iterator;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * @author Peter Kurfer
+ * Created on 10/6/17.
+ */
+class SimpleListTests {
+
+	private final Logger logger = LogManager.getLogger();
+	private SimpleList<Integer> testList;
+
+	@BeforeEach
+	void setup(){
+		testList = new SimpleListImpl<>();
+
+		testList.add(1);
+		testList.add(2);
+		testList.add(3);
+		testList.add(4);
+		testList.add(5);
+	}
+
+	@Test
+	void testAddElements(){
+		logger.info("Testing if adding and iterating elements is implemented correctly");
+		int counter = 0;
+		for(Object o : testList){
+			counter++;
+		}
+		assertEquals(5, counter);
+	}
+
+	@Test
+	void testSize(){
+		logger.info("Testing if size() method is implemented correctly");
+		assertEquals(5, testList.size());
+	}
+
+	@Test
+	void testFilterAnonymousClass(){
+		logger.info("Testing the filter possibilities by filtering for all elements greater 2");
+		SimpleList<Integer> result = testList.filter(new SimpleFilter<Integer>() {
+			@Override
+			public boolean include(Integer item) {
+				return item > 2;
+			}
+		});
+
+		for(Integer i : result){
+			assertTrue(i > 2);
+		}
+	}
+
+	@Test
+	void testFilterLambda(){
+		logger.info("Testing the filter possibilities by filtering for all elements which are dividable by 2");
+		SimpleList<Integer> result = testList.filter(o -> o % 2 == 0);
+		for(Integer i : result){
+			assertTrue(i % 2 == 0);
+		}
+	}
+
+	@Test
+	void testAddEmpty() throws Exception {
+		logger.info("Testing to add a new empty list element");
+		SimpleList<Person> l = new SimpleListImpl<>();
+		l.addDefault(Person.class);
+		assertEquals(1, l.size());
+	}
+
+	@Test
+	void testSimpleListMap(){
+		logger.info("Testing default map method");
+		SimpleList<Integer> mapped = testList.map(i -> i + 1);
+		assertEquals(5, mapped.size());
+		for(Integer i : mapped) {
+			assertTrue(i > 1);
+			assertTrue(i < 7);
+		}
+	}
+
+	@Test
+	void testMap() {
+		logger.info("Testing default map method by mapping every value to its square");
+		SimpleList<Double> result = testList.map(i -> Math.pow(i, 2));
+		Iterator<Integer> origIt = testList.iterator();
+		Iterator<Double> mapIt = result.iterator();
+		while (origIt.hasNext() && mapIt.hasNext()) {
+			assertEquals(Math.pow(origIt.next(), 2), mapIt.next(), 0.1);
+		}
+	}
+
+	@Test
+	void testSimpleListMapChangedType() {
+		logger.info("Testing default map method by mapping every integer to a char value");
+		SimpleList<Character> mapped = testList.map(i -> ((char) (i + 64)));
+		assertEquals(5, mapped.size());
+	}
+}
diff --git a/src/test/java/de/fhro/inf/prg3/a05/tests/models/Person.java b/src/test/java/de/fhro/inf/prg3/a05/tests/models/Person.java
new file mode 100644
index 0000000000000000000000000000000000000000..94b22b4c25c54454f7cbdec0179abd41e07415a8
--- /dev/null
+++ b/src/test/java/de/fhro/inf/prg3/a05/tests/models/Person.java
@@ -0,0 +1,71 @@
+package de.fhro.inf.prg3.a05.tests.models;
+
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+
+/**
+ * Demo model with an empty constructor to be able to test the addEmpty() method
+ * @author Peter Kurfer
+ * Created on 10/19/17.
+ */
+public class Person {
+
+	private String firstName;
+	private String lastName;
+
+	public Person() {
+	}
+
+	public Person(String firstName, String lastName) {
+		this.firstName = firstName;
+		this.lastName = lastName;
+	}
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public void setFirstName(String firstName) {
+		this.firstName = firstName;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public void setLastName(String lastName) {
+		this.lastName = lastName;
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) return true;
+
+		if (!(o instanceof Person)) return false;
+
+		Person person = (Person) o;
+
+		return new EqualsBuilder()
+				.append(getFirstName(), person.getFirstName())
+				.append(getLastName(), person.getLastName())
+				.isEquals();
+	}
+
+	@Override
+	public int hashCode() {
+		return new HashCodeBuilder(17, 37)
+				.append(getFirstName())
+				.append(getLastName())
+				.toHashCode();
+	}
+
+	@Override
+	public String toString() {
+		return new ToStringBuilder(this)
+				.append("firstName", firstName)
+				.append("lastName", lastName)
+				.toString();
+	}
+}
+