...
 
Commits (2)
package de.ostfalia.algo.ws18.s1;
/**
* A generic linked list node.
*
* @param <E> The type of the value this node contains.
*/
public class LinkedListNode<E> {
/**
* This node's value.
*/
private E value;
/**
* The next linked node.
*/
private LinkedListNode<E> next;
/**
* Create a node with the given value and no next node.
*
* @param value This node's value.
*/
public LinkedListNode(E value) {
this.value = value;
this.next = null;
}
public boolean hasNext() {
return this.next != null;
}
/**
* Get this node's value.
*
* @return This node's value.
*/
public E getValue() {
return this.value;
}
/**
* Set this node's value.
*
* @param value The new value.
*/
public void setValue(E value) {
this.value = value;
}
/**
* Get the next linked node.
*
* @return The next linked node.
*/
public LinkedListNode<E> getNext() {
return this.next;
}
/**
* Set the next linked node.
*
* @param next
*/
public void setNext(LinkedListNode<E> next) {
this.next = next;
}
......
package de.ostfalia.algo.ws18.s1;
import java.time.LocalDate;
import de.ostfalia.algo.ws18.base.Gender;
import de.ostfalia.algo.ws18.base.KindOfSport;
public class Main {
public static void main(String ...args) {
Management management = new Management();
management.checkpoint();
management.insert(new Member("Blümchen", "Benjamin", LocalDate.now(), Gender.M, KindOfSport.TANZEN));
System.out.println(management.checkpoint()/1000 + " ms für das erste insert");
management.insert(new Member("Kolumna", "Carla", LocalDate.now(), Gender.F, KindOfSport.RADSPORT));
System.out.println(management.checkpoint()/1000 + " ms für das zweite insert");
System.out.println("management hat " + management.size() + " Elemente, eingefügt in " + management.numberOfOperations());
management.checkpoint();
System.out.println("Suche Claudia Wexler: "
+ management.search("Wexler", "Claudia")
+ ", gefunden nach " + management.numberOfOperations()
+ " Operationen und " + management.checkpoint()/1000 + " ms");
}
}
......@@ -4,37 +4,67 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Optional;
import java.util.function.Predicate;
import de.ostfalia.algo.ws18.base.Gender;
import de.ostfalia.algo.ws18.base.IManagement;
import de.ostfalia.algo.ws18.base.IMember;
import de.ostfalia.algo.ws18.base.KindOfSport;
public class Management implements IManagement {
/**
* Track the number of operations.
*/
private int numberOfOperations = 0;
/**
* Track the execution time.
*/
private long lastCheckpointNs;
private Optional<LinkedListNode<IMember>> head = Optional.empty();
/**
* Current head node.
*/
private LinkedListNode<IMember> head;
/**
* Length of the list.
*/
private int size = 0;
boolean reversed = false;
/**
* Whether the list is reversed, i. e. the head is the tail.
*/
private boolean reversed = false;
/**
* Empty constructor.
*/
public Management() {
}
/**
* Insert from an array of strings.
*
* @param membersCsv Array of CSV rows.
*/
public Management(String[] membersCsv) {
for (String memberCsv : membersCsv) {
this.insert(new Member(memberCsv));
}
}
/**
* Read from the CSV file and insert.
*
* @param filename Path to the CSV file.
*/
public Management(String filename) {
this.importFromFile(filename);
}
private void importFromFile(String filename) {
/**
* Read from the CSV file and insert.
*
* @param filename Path to the CSV file.
*/
public void importFromFile(String filename) {
File file = new File(filename);
try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
......@@ -44,36 +74,25 @@ public class Management implements IManagement {
}
}
@Override
public int size() {
return this.size;
}
@Override
public boolean insert(IMember value) {
this.numberOfOperations++;
LinkedListNode<IMember> newHead = new LinkedListNode<IMember>(value);
if (this.head.isPresent()) {
newHead.setNext(this.head.get());
}
this.head = Optional.of(newHead);
this.size++;
return true; // TODO?
}
/**
* Create a filtered version of this list.
*
* @param criteria Criteria to filter for.
* @param breakAfterFirstMatch If true, return after the first match.
* @return A new list where all elements meet the given criteria.
*/
private Management filter(Predicate<IMember> criteria, boolean breakAfterFirstMatch) {
Management result = new Management();
if (!this.head.isPresent()) {
if (this.size == 0) {
return result;
}
// searches from head, inserts at head -> result is reversed
result.reverse();
LinkedListNode<IMember> currentNode = this.head.get();
LinkedListNode<IMember> currentNode = this.head;
do {
// traverse = 1 operation
this.numberOfOperations++;
IMember currentValue = currentNode.getValue();
......@@ -88,48 +107,126 @@ public class Management implements IManagement {
return result;
}
private Optional<IMember> search(Predicate<IMember> criteria) {
return this.filter(criteria, true).head.map(head -> head.getValue());
/**
* Find the first element that matches the given criteria.
*
* @param criteria Criteria to search for.
* @return The first element that matches the given criteria or null.
*/
private IMember search(Predicate<IMember> criteria) {
Management filteredList = this.filter(criteria, true);
if (filteredList.size() == 0) {
return null;
} else {
return filteredList.head.getValue();
}
}
/**
* Count the number of elements that match the given criteria.
*
* @param criteria Criteria to filter for.
* @return The number of elements that match the given criteria.
*/
private long size(Predicate<IMember> criteria) {
return this.filter(criteria, false).size;
}
/**
* Reverse the order of the list.
*/
public void reverse() {
this.reversed = !this.reversed;
}
/**
* @return The length of this list.
*/
@Override
public int size() {
return this.size;
}
/**
* Add an element at the start of the list.
* Replace the current head with a new node and link this node to the old head.
*
* @return TODO?
*/
@Override
public boolean insert(IMember value) {
this.numberOfOperations++;
LinkedListNode<IMember> newHead = new LinkedListNode<IMember>(value);
if (this.head != null) {
newHead.setNext(this.head);
}
this.head = newHead;
this.size++;
return true; // TODO?
}
/**
* Find the first member with the given key.
*
* @param key The key to search for.
* @return The member or null.
*/
@Override
public IMember search(long key) {
return this.search(member -> member.getKey() == key).orElse(null);
return this.search(member -> member.getKey() == key);
}
/**
* Find the first member with the given name.
*
* @param name The name of the member.
* @param firstName first name of the member.
* @return The member or null.
*/
@Override
public IMember search(String name, String firstName) {
return this.search(member -> member.getName().equals(name)
&& member.getFirstName().equals(firstName)).orElse(null);
&& member.getFirstName().equals(firstName));
}
/**
* Count the number of members which have an association to the given kindOfSport.
*
* @param kindOfSport The kindOfSport of the members.
* @return The number of members with the given kindOfSport.
*/
@Override
public int size(KindOfSport kindOfSport) {
return (int) this.size(member -> member.getKindOfSport().equals(kindOfSport));
}
/**
* Return the members which have an association to the given kindOfSport.
*
* @param kindOfSport The kindOfSport of the members.
* @return An array of the members with the given kindOfSport.
*/
@Override
public IMember[] discipline(KindOfSport kindOfSport) {
return this.filter(member -> member.getKindOfSport().equals(kindOfSport), false)
.toArray();
}
/**
* Convert the list to an array.
*
* @return The elements of this list as array.
*/
@Override
public IMember[] toArray() {
IMember[] array = new IMember[this.size];
if (!this.head.isPresent()) {
if (this.size() == 0) {
return array;
}
LinkedListNode<IMember> currentNode = this.head.get();
LinkedListNode<IMember> currentNode = this.head;
for (int index = 0; index < this.size; index++) {
if (reversed) {
......@@ -143,10 +240,26 @@ public class Management implements IManagement {
return array;
}
/**
* Reset the number of operation counter and get the last value.
*
* @return The number of operations recorded since the last call.
*/
@Override
public int numberOfOperations() {
int numberOfOperations = this.numberOfOperations;
this.numberOfOperations = 0;
return numberOfOperations;
}
/**
* Reset the timer and get the time difference in ns.
*
* @return Nanoseconds since the last call.
*/
public long checkpoint() {
long nanoseconds = this.lastCheckpointNs;
this.lastCheckpointNs = System.nanoTime();
return this.lastCheckpointNs - nanoseconds;
}
}
......@@ -104,10 +104,7 @@ public class Member implements IMember {
String nameKeyPart = encodeLetters(member.name.substring(0, 1));
String surnameKeyPart = encodeLetters(member.firstname.substring(0, 1));
String dateKeyPart = encodeDate(member.date);
String key = String.format("%s%s%s",
nameKeyPart,
surnameKeyPart,
dateKeyPart);
String key = nameKeyPart + surnameKeyPart + dateKeyPart;
return Long.valueOf(key);
}
......@@ -118,7 +115,7 @@ public class Member implements IMember {
* @return A String ttmmjjjj.
*/
private static String encodeDate(LocalDate date) {
return String.format("%02d%02d%02d",
return String.format("%02d%02d%02d", // 2 digits, left pad
date.getDayOfMonth(),
date.getMonthValue(),
date.getYear());
......@@ -165,6 +162,7 @@ public class Member implements IMember {
/**
* Return this member as string.
*/
@Override
public String toString() {
return this.key + ", "
+ this.name + ", "
......@@ -179,30 +177,37 @@ public class Member implements IMember {
*
* @return @see Comparable
*/
@Override
public int compareTo(IMember member) {
return Long.compare(this.key, member.getKey());
}
@Override
public String getName() {
return this.name;
}
@Override
public Gender getGender() {
return this.gender;
}
@Override
public LocalDate getDate() {
return this.date;
}
@Override
public String getFirstName() {
return this.firstname;
}
@Override
public long getKey() {
return this.key;
}
@Override
public KindOfSport getKindOfSport() {
return this.kindOfSport;
}
......