From 1b7f30c8b22c9a4a942ec9b018863c8bb5151166 Mon Sep 17 00:00:00 2001 From: Martin Goik <goik@hdm-stuttgart.de> Date: Mon, 2 Nov 2015 19:06:22 +0100 Subject: [PATCH] Prerequisite stream exercises --- Doc/Sd1/objectsClasses.xml | 19 +- Doc/Sda1/dom.xml | 163 +++++++++++++++++- .../mi/javastreams/FunctionalProcessing.java | 40 ----- .../Solution}/.gitignore | 0 .../{Javastreams => Streams/Solution}/pom.xml | 4 +- .../hdm_stuttgart/mi/javastreams/Student.java | 111 ++++++------ .../Solution}/src/main/resources/log4j2.xml | 0 .../mi/javastreams/FunctionalTests.java | 20 +++ P/Sda1/Streams/Template/.gitignore | 4 + P/Sda1/Streams/Template/pom.xml | 46 +++++ .../mi/javastreams/RosterTest.java | 0 .../hdm_stuttgart/mi/javastreams/Student.java | 102 +++++++++++ .../Template/src/main/resources/log4j2.xml | 21 +++ .../mi/javastreams/FunctionalTests.java | 133 ++++++++++++++ P/pom.xml | 3 +- 15 files changed, 557 insertions(+), 109 deletions(-) delete mode 100644 P/Sda1/Javastreams/src/main/java/de/hdm_stuttgart/mi/javastreams/FunctionalProcessing.java rename P/Sda1/{Javastreams => Streams/Solution}/.gitignore (100%) rename P/Sda1/{Javastreams => Streams/Solution}/pom.xml (93%) rename P/Sda1/{Javastreams => Streams/Solution}/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java (60%) rename P/Sda1/{Javastreams => Streams/Solution}/src/main/resources/log4j2.xml (100%) rename P/Sda1/{Javastreams => Streams/Solution}/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java (90%) create mode 100644 P/Sda1/Streams/Template/.gitignore create mode 100644 P/Sda1/Streams/Template/pom.xml rename P/Sda1/{Javastreams => Streams/Template}/src/main/java/de/hdm_stuttgart/mi/javastreams/RosterTest.java (100%) create mode 100644 P/Sda1/Streams/Template/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java create mode 100644 P/Sda1/Streams/Template/src/main/resources/log4j2.xml create mode 100644 P/Sda1/Streams/Template/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java diff --git a/Doc/Sd1/objectsClasses.xml b/Doc/Sd1/objectsClasses.xml index a0c033846..eed9c5e00 100644 --- a/Doc/Sd1/objectsClasses.xml +++ b/Doc/Sd1/objectsClasses.xml @@ -84,8 +84,8 @@ <title>Generating <xref linkend="glo_Javadoc"/>.</title> <para>Java includes the powerful <xref linkend="glo_Javadoc"/> - documentation generating subsystem. There are multiple ways to - generate HTML documentation from your own Java code:</para> + documentation generating subsystem. There are multiple ways to generate + HTML documentation from your own Java code:</para> <itemizedlist> <listitem> @@ -98,9 +98,9 @@ </listitem> <listitem> - <para>Using Eclipse. Just select your project in the package view - and choose <guimenu>Project</guimenu> <guisubmenu>Generate Javadoc - ...</guisubmenu> . See <link + <para>Using <productname>Eclipse</productname>. Just select your + project in the package view and choose <guimenu>Project</guimenu> + <guisubmenu>Generate Javadoc ...</guisubmenu> . See <link xlink:href="https://www.youtube.com/watch?v=FCJKTT86vP0">related video</link> in case of problems. You may also fancy <link xlink:href="http://www.itcsolutions.eu/2010/12/23/tutorial-java-62-2-how-to-generate-javadoc-in-eclipse-or-netbean">How @@ -139,8 +139,9 @@ <filename>~/git/GoikLectures</filename>. This step is required only once.</para> - <para>If you fancy working on console level you may simply issue - the following command instead:</para> + <para>If you fancy working on console level you may as well issue + the following command instead using + <productname>Eclipse</productname>:</para> </informalfigure> <programlisting language="none">git clone https://version.mi.hdm-stuttgart.de/git/GoikLectures</programlisting> @@ -151,8 +152,8 @@ <guisubmenu>File</guisubmenu> <guimenuitem>Import</guimenuitem> <guisubmenu>Maven</guisubmenu> <guimenuitem>Existing Maven Projects</guimenuitem>. Then choose the desired project below - <filename>GoikLectures/P/Sd1</filename> (like e.g. - <filename>GoikLectures/P/Sd1/interest/V1</filename>) and hit + <filename>GoikLectures/P</filename> like e.g. + <filename>GoikLectures/P/Sd1/interest/V1</filename> and hit <guibutton>Finish</guibutton>.</para> </listitem> </orderedlist> diff --git a/Doc/Sda1/dom.xml b/Doc/Sda1/dom.xml index 76821f1f9..96379ede2 100644 --- a/Doc/Sda1/dom.xml +++ b/Doc/Sda1/dom.xml @@ -501,7 +501,7 @@ Article: 200W Stereo Amplifier, order number: 9921</programlisting> all elements by <link xlink:href="https://en.wikipedia.org/wiki/Tree_traversal#Pre-order">depth first pre order</link> traversal among with their respective - nesting depth and possibly attributes.</para> + nesting depth and attributes.</para> <para>Provide the total numbers of elements and attributes as well. For the above input the expected output of your @@ -536,6 +536,167 @@ Document contains 15 elements and 3 attributes.</programlisting> </qandaset> </section> + <section xml:id="sda1SectFunctionalBasics"> + <title> Short reminder to functional programming elements in <xref + linkend="glo_Java"/>.</title> + + <qandaset defaultlabel="qanda" xml:id="sda1QandaFunctionalBasics"> + <qandadiv> + <qandaentry> + <question> + <para>As a courtesy we remind all participants to functional + programming elements being dealt with in <link + xlink:href="https://www.hdm-stuttgart.de/studenten/stundenplan/vorlesungsverzeichnis/vorlesung_detail?vorlid=5211589" + xml:lang="de">Softwareentwicklung 2</link>.</para> + + <para>This exercise has been derived from <link + xlink:href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html">Lambda + Expressions - The Java™ Tutorials</link>. Depending on your own + personal knowledge you may want to start that trail + beforehand.</para> + + <para>Import the following project template into <xref + linkend="glo_Soft_Eclipse"/>:</para> + + <annotation> + <para>P/Sda1/Streams/Template</para> + </annotation> + + <para>This template contains:</para> + + <orderedlist> + <listitem> + <para>Some boilerplate code in + <classname>de.hdm_stuttgart.mi.javastreams.RosterTest</classname> + modified from <link + xlink:href="https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html">Lambda + Expressions - The Java™ Tutorials</link>. Execution does + make sense when reading Oracle's trail in parallel.</para> + </listitem> + + <listitem> + <para>A unit test class + <classname>de.hdm_stuttgart.mi.javastreams.FunctionalTests</classname>. + This is your place to do the actual work.</para> + </listitem> + </orderedlist> + + <para>This exercises idea is: </para> + + <orderedlist> + <listitem> + <para>Create stream based solutions.</para> + </listitem> + + <listitem> + <para>Write a test for each test yourself.</para> + </listitem> + </orderedlist> + + <para>The first test of + <classname>de.hdm_stuttgart.mi.javastreams.FunctionalTests</classname> + is intended to serve as a blueprint:</para> + + <programlisting language="java"> /** + * Order all male students by email and create a List<String> of their respective + * names in that order eliminating possible duplicates: <co + linkends="sda1CalloutFunctionalJunit-1" + xml:id="sda1CalloutFunctionalJunit-1-co"/> + * + * "Bob", 2, Student.Sex.MALE, "bob@uk.edu" <co + linkends="sda1CalloutFunctionalJunit-2" + xml:id="sda1CalloutFunctionalJunit-2-co"/> + * "Fred", 2, Student.Sex.MALE, "fred@example.com" + * "George", 4, Student.Sex.MALE, "george@math.edu" + * "Jane", 1, Student.Sex.FEMALE, "jane@kiv.de" + * "Kim", 2, Student.Sex.FEMALE, "wilde@serious.de" + * + * ==> {"Bob", "Fred", "George"} <co + linkends="sda1CalloutFunctionalJunit-3" + xml:id="sda1CalloutFunctionalJunit-3-co"/> + * + */ + @Test + public void allMaleDistinctNameOrderedByEmail() { + + List<String> emails = <co linkends="sda1CalloutFunctionalJunit-4" + xml:id="sda1CalloutFunctionalJunit-4-co"/> + roster. + stream(). + filter(s -> s.gender == Sex.MALE). + sorted((s1, s2) -> s1.getEmailAddress().compareTo(s2.getEmailAddress())). + map(Student::getName). + distinct(). + collect(Collectors.toList()); + + assertThat(emails, <co linkends="sda1CalloutFunctionalJunit-5" + xml:id="sda1CalloutFunctionalJunit-5-co"/> + Matchers.<List<String>> equalTo( + ImmutableList.of("Bob", "Fred", "George") + ) + ); + }</programlisting> + + <calloutlist> + <callout arearefs="sda1CalloutFunctionalJunit-1-co" + xml:id="sda1CalloutFunctionalJunit-1"> + <para>An informal description of the desired outcome.</para> + </callout> + + <callout arearefs="sda1CalloutFunctionalJunit-2-co" + xml:id="sda1CalloutFunctionalJunit-2"> + <para>A list of records illustrating a processing + step.</para> + </callout> + + <callout arearefs="sda1CalloutFunctionalJunit-3-co" + xml:id="sda1CalloutFunctionalJunit-3"> + <para>An informal description of the desired output.</para> + </callout> + + <callout arearefs="sda1CalloutFunctionalJunit-4-co" + xml:id="sda1CalloutFunctionalJunit-4"> + <para>A stream pipeline yielding the result.</para> + </callout> + + <callout arearefs="sda1CalloutFunctionalJunit-5-co" + xml:id="sda1CalloutFunctionalJunit-5"> + <para>A unit test checking for correctness.</para> + </callout> + </calloutlist> + + <tip> + <para>Unit tests for this type of work frequently requires + comparing <classname + xlink:href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html">List</classname> + and <classname + xlink:href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html">Map</classname> + objects. The above code <coref + linkend="sda1CalloutFunctionalJunit-5-co"/> uses <link + xlink:href="https://github.com/google/guava/wiki">Guava</link> + for <link + xlink:href="https://github.com/google/guava/wiki/ImmutableCollectionsExplained">immutable + collections</link> creation representing expected + outcomes.</para> + + <para>On the other end <productname + xlink:href="http://hamcrest.org/">Hamcrest</productname> + allows for using these collections <link + xlink:href="https://code.google.com/p/hamcrest/wiki/Tutorial">to + be compared</link> with actual test outcomes.</para> + </tip> + </question> + + <answer> + <annotation> + <para>P/Sda1/Streams/Solution</para> + </annotation> + </answer> + </qandaentry> + </qandadiv> + </qandaset> + </section> + <section xml:id="sda1SectDomCreateHtml"> <title>Creating HTML output</title> diff --git a/P/Sda1/Javastreams/src/main/java/de/hdm_stuttgart/mi/javastreams/FunctionalProcessing.java b/P/Sda1/Javastreams/src/main/java/de/hdm_stuttgart/mi/javastreams/FunctionalProcessing.java deleted file mode 100644 index 1727fe636..000000000 --- a/P/Sda1/Javastreams/src/main/java/de/hdm_stuttgart/mi/javastreams/FunctionalProcessing.java +++ /dev/null @@ -1,40 +0,0 @@ -package de.hdm_stuttgart.mi.javastreams; - -import java.util.List; - - -public class FunctionalProcessing { - - static final List<Student> roster = Student.createRoster(); - - public static void main( String[] args ) { - - markSumAllStudentsMarksHavingEmail_Dot_de(); - - - -// roster.stream() -// .filter(p -> p.emailAddress.endsWith(".edu")) -// .mapToInt(Person::getAge) -// .average().ifPresent(System.out::println);; - - -// roster.stream() -// .filter(p -> p.emailAddress.endsWith(".edu")) -// .forEach(System.out::println); - - - - } - - /** - * Summing up marks from all students having a German email address - */ - public static int markSumAllStudentsMarksHavingEmail_Dot_de() { - return roster.stream() - .filter(p -> p.emailAddress.endsWith(".de")) - .mapToInt(Student::getMark) - .reduce(0, (a, b) -> a + b); - } - -} diff --git a/P/Sda1/Javastreams/.gitignore b/P/Sda1/Streams/Solution/.gitignore similarity index 100% rename from P/Sda1/Javastreams/.gitignore rename to P/Sda1/Streams/Solution/.gitignore diff --git a/P/Sda1/Javastreams/pom.xml b/P/Sda1/Streams/Solution/pom.xml similarity index 93% rename from P/Sda1/Javastreams/pom.xml rename to P/Sda1/Streams/Solution/pom.xml index a391cf0d6..2cf028248 100644 --- a/P/Sda1/Javastreams/pom.xml +++ b/P/Sda1/Streams/Solution/pom.xml @@ -7,12 +7,12 @@ <artifactId>lecturenotes-pom</artifactId> <version>1.0</version> - <relativePath>../../pom.xml</relativePath> + <relativePath>../../../pom.xml</relativePath> </parent> <groupId>de.hdm_stuttgart.mi</groupId> <artifactId>javastreams</artifactId> - <version>0.0.1-SNAPSHOT</version> + <version>0.8</version> <packaging>jar</packaging> <name>Javastreams</name> diff --git a/P/Sda1/Javastreams/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java b/P/Sda1/Streams/Solution/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java similarity index 60% rename from P/Sda1/Javastreams/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java rename to P/Sda1/Streams/Solution/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java index 2e42d91d8..8e3a64d9f 100644 --- a/P/Sda1/Javastreams/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java +++ b/P/Sda1/Streams/Solution/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java @@ -30,74 +30,73 @@ package de.hdm_stuttgart.mi.javastreams; * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + import java.util.Arrays; import java.util.List; public class Student { - - public static List<Student> createRoster() { - + + public static List<Student> createRoster() { // Create test data records + final Student[] roster = new Student[] { - new Student("Fred", 2, Student.Sex.MALE, "fred@example.com") - ,new Student("Jane", 1, Student.Sex.FEMALE, "jane@kiv.de") - ,new Student("George", 4, Student.Sex.MALE, "george@math.edu") - ,new Student("Bob", 2, Student.Sex.MALE, "bob@uk.edu") - ,new Student("Kim", 2, Student.Sex.FEMALE, "wilde@serious.de") - }; - + new Student("Fred", 2, Student.Sex.MALE, "fred@example.com") + ,new Student("Jane", 1, Student.Sex.FEMALE, "jane@kiv.de") + ,new Student("George", 4, Student.Sex.MALE, "george@math.edu") + ,new Student("Bob", 2, Student.Sex.MALE, "bob@uk.edu") + ,new Student("Kim", 2, Student.Sex.FEMALE, "wilde@serious.de") + }; + return Arrays.asList(roster); - } - - - public enum Sex { - MALE("male"), FEMALE("female"); - - final String extern; - - private Sex(final String extern) {this.extern = extern;} - public String toString(){return extern;} - } - - String name; - int mark; - Sex gender; - String emailAddress; - - Student(String name, int mark , - Sex gender, String email) { - this.name = name; - this.mark = mark; - this.gender = gender; - this.emailAddress = email; - } - - public int getMark() { - return mark; - } - public Sex getGender() { - return gender; - } - - public String getName() { - return name; - } - - public String getEmailAddress() { - return emailAddress; - } - - public static int compareByMark(Student a, Student b) { - return a.mark - b.mark; - } + } + + public enum Sex { + MALE("male"), FEMALE("female"); + + final String extern; + + private Sex(final String extern) {this.extern = extern;} + public String toString(){return extern;} + } + + String name; + int mark; + Sex gender; + String emailAddress; + + Student(String name, int mark , + Sex gender, String email) { + this.name = name; + this.mark = mark; + this.gender = gender; + this.emailAddress = email; + } + + public int getMark() { + return mark; + } + public Sex getGender() { + return gender; + } + + public String getName() { + return name; + } + + public String getEmailAddress() { + return emailAddress; + } + + public static int compareByMark(Student a, Student b) { + return a.mark - b.mark; + } @Override public String toString() { return getName() + "(" + gender + ", " + getEmailAddress() + ", mark=" + getMark() + ")"; } - + public void print() { System.out.println(this); } - + } \ No newline at end of file diff --git a/P/Sda1/Javastreams/src/main/resources/log4j2.xml b/P/Sda1/Streams/Solution/src/main/resources/log4j2.xml similarity index 100% rename from P/Sda1/Javastreams/src/main/resources/log4j2.xml rename to P/Sda1/Streams/Solution/src/main/resources/log4j2.xml diff --git a/P/Sda1/Javastreams/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java b/P/Sda1/Streams/Solution/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java similarity index 90% rename from P/Sda1/Javastreams/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java rename to P/Sda1/Streams/Solution/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java index 4077291d9..5aa29f1d8 100644 --- a/P/Sda1/Javastreams/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java +++ b/P/Sda1/Streams/Solution/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java @@ -4,6 +4,7 @@ import static org.hamcrest.MatcherAssert.assertThat; import java.util.List; import java.util.Map; +import java.util.OptionalDouble; import java.util.stream.Collectors; import org.hamcrest.Matchers; @@ -71,6 +72,25 @@ public class FunctionalTests { .reduce(0, (a, b) -> a + b) ); } + + /** + * Get the average mark of all female students as double value. + * + * Female marks: {1, 2}, sum == 3, average = 3. / 2 == 1.5 + * + */ + @Test + public void averageMarkFemaleStudents() { + + final OptionalDouble femaleAverage = roster.stream(). + filter(s -> s.gender == Sex.FEMALE). + mapToInt(Student::getMark). + average(); + + Assert.assertTrue(femaleAverage.isPresent()); + Assert.assertEquals((1 + 2) / 2., femaleAverage.getAsDouble(), 1.E-20); + + } /** * Group students by sex and collect their respective names: diff --git a/P/Sda1/Streams/Template/.gitignore b/P/Sda1/Streams/Template/.gitignore new file mode 100644 index 000000000..a1c3ab4d0 --- /dev/null +++ b/P/Sda1/Streams/Template/.gitignore @@ -0,0 +1,4 @@ +/target/ +/.settings/ +.classpath +.project diff --git a/P/Sda1/Streams/Template/pom.xml b/P/Sda1/Streams/Template/pom.xml new file mode 100644 index 000000000..2cf028248 --- /dev/null +++ b/P/Sda1/Streams/Template/pom.xml @@ -0,0 +1,46 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>de.hdm-stuttgart.mi</groupId> + <artifactId>lecturenotes-pom</artifactId> + <version>1.0</version> + + <relativePath>../../../pom.xml</relativePath> + </parent> + + <groupId>de.hdm_stuttgart.mi</groupId> + <artifactId>javastreams</artifactId> + <version>0.8</version> + <packaging>jar</packaging> + + <name>Javastreams</name> + + <url>http://www.mi.hdm-stuttgart.de/freedocs</url> + + <dependencies> + + <dependency> + <groupId>org.jdom</groupId> + <artifactId>jdom2</artifactId> + <version>${org.jdom.jdom2.version}</version> + </dependency> + + <dependency> + <groupId>org.hamcrest</groupId> + <artifactId>hamcrest-all</artifactId> + <version>1.3</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>18.0</version> + <scope>test</scope> + </dependency> + + </dependencies> + +</project> diff --git a/P/Sda1/Javastreams/src/main/java/de/hdm_stuttgart/mi/javastreams/RosterTest.java b/P/Sda1/Streams/Template/src/main/java/de/hdm_stuttgart/mi/javastreams/RosterTest.java similarity index 100% rename from P/Sda1/Javastreams/src/main/java/de/hdm_stuttgart/mi/javastreams/RosterTest.java rename to P/Sda1/Streams/Template/src/main/java/de/hdm_stuttgart/mi/javastreams/RosterTest.java diff --git a/P/Sda1/Streams/Template/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java b/P/Sda1/Streams/Template/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java new file mode 100644 index 000000000..8e3a64d9f --- /dev/null +++ b/P/Sda1/Streams/Template/src/main/java/de/hdm_stuttgart/mi/javastreams/Student.java @@ -0,0 +1,102 @@ +package de.hdm_stuttgart.mi.javastreams; + +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * - Neither the name of Oracle or the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +import java.util.Arrays; +import java.util.List; + +public class Student { + + public static List<Student> createRoster() { // Create test data records + + final Student[] roster = new Student[] { + new Student("Fred", 2, Student.Sex.MALE, "fred@example.com") + ,new Student("Jane", 1, Student.Sex.FEMALE, "jane@kiv.de") + ,new Student("George", 4, Student.Sex.MALE, "george@math.edu") + ,new Student("Bob", 2, Student.Sex.MALE, "bob@uk.edu") + ,new Student("Kim", 2, Student.Sex.FEMALE, "wilde@serious.de") + }; + + return Arrays.asList(roster); + } + + public enum Sex { + MALE("male"), FEMALE("female"); + + final String extern; + + private Sex(final String extern) {this.extern = extern;} + public String toString(){return extern;} + } + + String name; + int mark; + Sex gender; + String emailAddress; + + Student(String name, int mark , + Sex gender, String email) { + this.name = name; + this.mark = mark; + this.gender = gender; + this.emailAddress = email; + } + + public int getMark() { + return mark; + } + public Sex getGender() { + return gender; + } + + public String getName() { + return name; + } + + public String getEmailAddress() { + return emailAddress; + } + + public static int compareByMark(Student a, Student b) { + return a.mark - b.mark; + } + + @Override + public String toString() { + return getName() + "(" + gender + ", " + getEmailAddress() + ", mark=" + getMark() + ")"; + } + + public void print() { + System.out.println(this); + } + +} \ No newline at end of file diff --git a/P/Sda1/Streams/Template/src/main/resources/log4j2.xml b/P/Sda1/Streams/Template/src/main/resources/log4j2.xml new file mode 100644 index 000000000..cf45d9929 --- /dev/null +++ b/P/Sda1/Streams/Template/src/main/resources/log4j2.xml @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<Configuration> + <Appenders> + <File name="A1" fileName="A1.log" append="false"> + <PatternLayout pattern="%t %-5p %c{2} - %m%n"/> + </File> + <Console name="STDOUT" target="SYSTEM_OUT"> + <PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/> + </Console> + </Appenders> + <Loggers> + + <!-- You my want to define class or package level per-logger rules --> + <Logger name="de.hdm_stuttgart.mi.javastreams.App" level="debug"> + <AppenderRef ref="A1"/> + </Logger> + <Root level="info"> + <AppenderRef ref="STDOUT"/> + </Root> + </Loggers> +</Configuration> \ No newline at end of file diff --git a/P/Sda1/Streams/Template/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java b/P/Sda1/Streams/Template/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java new file mode 100644 index 000000000..094b6c4b8 --- /dev/null +++ b/P/Sda1/Streams/Template/src/test/java/de/hdm_stuttgart/mi/javastreams/FunctionalTests.java @@ -0,0 +1,133 @@ +package de.hdm_stuttgart.mi.javastreams; + +import static org.hamcrest.MatcherAssert.assertThat; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.hamcrest.Matchers; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; + +import de.hdm_stuttgart.mi.javastreams.Student.Sex; + +/** + * Testing functional queries. + */ +public class FunctionalTests { + + final List<Student> roster = Student.createRoster(); + + /** + * Order all male students by email and create a List<String> of their respective + * names in that order eliminating possible duplicates: + * + * "Bob", 2, Student.Sex.MALE, "bob@uk.edu" + * "Fred", 2, Student.Sex.MALE, "fred@example.com" + * "George", 4, Student.Sex.MALE, "george@math.edu" + * "Jane", 1, Student.Sex.FEMALE, "jane@kiv.de" + * "Kim", 2, Student.Sex.FEMALE, "wilde@serious.de" + * + * ==> {"Bob", "Fred", "George"} + * + */ + @Test + public void allMaleDistinctNameOrderedByEmail() { + + List<String> emails = + roster. + stream(). + filter(s -> s.gender == Sex.MALE). + sorted((s1, s2) -> s1.getEmailAddress().compareTo(s2.getEmailAddress())). + map(Student::getName). + distinct(). + collect(Collectors.toList()); + + assertThat(emails, + Matchers.<List<String>> equalTo( + ImmutableList.of("Bob", "Fred", "George") + ) + ); + } + + /** + * Summing up all students' marks having a German email address: + * + * "Jane", 1, Student.Sex.FEMALE, "jane@kiv.de" + * "Kim", 2, Student.Sex.FEMALE, "wilde@serious.de" + * + */ + @Test + public void markSumAllStudentsMarksHavingEmail_Dot_de() { + // TODO + } + + /** + * Get the average mark of all female students as double value. + * + */ + @Test + public void averageMarkFemaleStudents() { + // TODO + } + + /** + * Create a Map<Student.Sex, List<String>> grouping students by sex and collecting + * their respective names: + * + * Female: + * "Jane" + * "Kim" + * + * Male: + * "Fred" + * "George" + * "Bob" + * + */ + @Test + public void studentNamesBySex() { + + final Map<Student.Sex, List<String>> studentnamesBySex = null; // TODO + + // See + // stackoverflow.com/questions/2509293/map-equality-using-hamcrest#answer-29680356 + assertThat(studentnamesBySex, + Matchers.<Map<Student.Sex, List<String>>> equalTo( + ImmutableMap.of ( + Student.Sex.MALE, ImmutableList.of("Fred", "George", "Bob") + ,Student.Sex.FEMALE, ImmutableList.of("Jane", "Kim") + ) + ) + ); + } + + /** + * Create a Map<Integer, Integer> of student's marks among with their corresponding frequencies: + * + * Mark 1: "Jane" --- 1 student + * Mark 2: "Fred", "Bob", "Kim" --> 3 students + * Mark 4: "George" --> 1 student + * + */ + @Test + public void markingFrequencies() { + // TODO + } + + /** + * Create a Map<String, List<String>> grouping student's names by mark: + * + * Mark 1: {"Jane"} + * Mark 2: {"Fred", "Bob", "Kim"} + * Mark 4: {"George"} + * + */ + @Test + public void studentsByMark() { + // TODO + } +} diff --git a/P/pom.xml b/P/pom.xml index 0eada25cf..8d9fd18d4 100644 --- a/P/pom.xml +++ b/P/pom.xml @@ -118,7 +118,8 @@ <module>Sda1/InsertGui/V2</module> <module>Sda1/InsertGui/V4</module> - <module>Sda1/Javastreams</module> + <module>Sda1/Streams/Solution</module> + <module>Sda1/Streams/Template</module> <module>Sda1/Jdom/Catalog2Xhtml</module> <module>Sda1/Jdom/Elements</module> -- GitLab