# Studentenverwaltung mit Hilfe einer Hashfunktion



## zabrinaa (25. Mai 2018)

Hallo zusammen,

die nachfolgende Aufgabe bearbeite ich nun seit über 2 Wochen. Zum größten Teil klappte dies auch reibungslos, allerdings stellte sich bei der Abfrage durch einen JUnit-Test ein scheinbar kleiner Fehler heraus, der nun die Abgabe der Aufgabe verhindert. Auch nach mehreren Abgleichen mit den Codes meine Kommilitonen konnte ich den Fehler nicht ausmachen und hoffe nun, dass mir hier weitergeholfen werden kann. 

Aufgabenstellung:
"In diesem Beispiel modellieren Sie eine Studentenverwaltung mittels einer „Hashtabelle“. Es handelt sich dabei um eine Datenstruktur (Indexstruktur) in die Studierende eingefügt und gelöscht werden können und in der nach Studierenden gesucht werden kann. Die Studenten werden dabei eindeutig durch ihre Matrikelnummer identifiziert."

Zur Implementierung der Studentenverwaltung werden folgende Klassen benötigt:
Student: beschreibt einen Studenten mit Attributen für: Name, Studiengang, Matrikelnummer;
StudentList: einfach verkettete Liste von Studenten;
HashTableStudent: enthält ein Array der Größe SIZE von StudentList und eine Hash- Funktion die eine Matrikelnummer auf einen Array-Index zwischen 0 und (SIZE-1) abbildet;
HashTableInteractiv: enthält die main- Methode welche den Ein/Ausgabedialog implementiert"

Der Fehler tritt beim JUnit-Test in der Zeile
"assertEquals("HashTable should be empty!", 0, toTest.getStudentCount());" 
auf. Da anstatt 0 der Wert 1 herauskommt. Leider ist es mir bisher nicht gelungen festzustellen woran dies liegen könnte. Ich danke schon einmal im Voraus für jegliche Hilfe!

Mit freundlichen Grüßen 
Sabrina


```
public class Student {

    private String name;
    private String studyCourse;
    private int matrikulationNr;

    public Student next;

    Student(String name, String studyCourse, int matrikulationNr) {
        this.name = name;
        this.studyCourse = studyCourse;
        this.matrikulationNr = matrikulationNr;

    }

    public String getName() {
        return this.name;

    }

    public void setName(String name) {
        this.name = name;

    }

    public String getStudyCourse() {
        return this.studyCourse;

    }

    public void setStudyCourse(String course) {

        this.studyCourse = course;
    }

    public int getMatrikulationNr() {
        return matrikulationNr;
    }

    public String toString() {
        return String.format("Name: %s \n" + "Studiengang: %s , \n" + "Matrikelnummer: %s ", name, studyCourse,
                matrikulationNr);

    }
}
```


```
public class StudentList {

    private Student head;
    private int count = 0;

    public StudentList() {
        head = null;
    }

    public boolean insert(Student stud) {
        Student toinsert = stud; // neuer Knoten, mit aktuellem Wert
        Student p = head; // Hilfsknoten zum Iterieren
        Student prev = null;

        if (search(toinsert.getMatrikulationNr()) == null) {
            while (p != null && p.getMatrikulationNr() < stud.getMatrikulationNr()) { // finden
                prev = p;
                p = p.next;
            }
            toinsert.next = p;
            if (p == head) { // neuer Knoten vorne einfügen
                head = toinsert;
                count++;
            } else {
                prev.next = toinsert;
                count++;
            }
            return true;

        }
        return false;
    }

    public Student search(int matrikel) {

        Student p = head; // Hilfsknoten zum Iterieren

        while (p != null && p.getMatrikulationNr() <= matrikel) { // über die
                                                                    // Listenelemente
                                                                    // iterieren
            if (p.getMatrikulationNr() == matrikel) {
                return p;

            }
            p = p.next;
        }
        return null;
    }

    public Student delete(int matrikel) {

        Student p = head;
        Student prev = null;
        Student rem = null;
        while (p != null && p.getMatrikulationNr() != matrikel) {

            prev = p;
            p = p.next;

            if (p != null) {
                rem = p;
                if (p == head) {
                    head = p.next;
                    count--;

                } else
                    prev.next = p.next;
                count--;

            }
            return rem;
        }
        return null;
    }

    public int getSize() {

        return count;

    }

    @Override
    public String toString() {
        return String.format("StudentList with %s Students", getSize());
    }
}
```


```
public class HashTableStudent {
    // Länge des Arrays, definiert als konstanter int mit dem Wert 20
    // (Arrayindizes von 0 bis 19)
    private static final int SIZE = 20;

    // das Array mit den „Buckets“ (StudentList)

    private StudentList[] studArray = new StudentList[SIZE];

    // default Konstruktor, initialisiert studArray
    public HashTableStudent() {
        studArray = new StudentList[SIZE];
        for (int i = 0; i < SIZE; i++) {
            studArray[i] = null;
        }
    }

    // fügt einen Studenten in die Datenstruktur ein
    public boolean insert(Student stud) {
        int addr = getHashCode(stud.getMatrikulationNr());
        if (studArray[addr] == null) {
            studArray[addr] = new StudentList();
        }
        return studArray[addr].insert(stud);

    }

    // sucht einen Studenten anhand der Matrikelnummer und gibt ihn zurück
    public Student search(int matrikel) {
        int addr = getHashCode(matrikel);
        return studArray[addr].search(matrikel);

    }

    // entfernt den Studenten mit der Matrikelnumer matrikel und gibt ihn zurück
    public Student delete(int matrikel) {
        int addr = getHashCode(matrikel);

        return studArray[addr].delete(matrikel);

    }

    // ermittelt die Anzahl der „eingeschriebenen“ Studenten
    public int getStudentCount() {
        int size = 0;
        for (int i = 0; i < studArray.length; i++) {
            if (studArray[i] != null)
                size += studArray[i].getSize();
        }
        return size;
    }

    private int getHashCode(int matrikel) {
        return (matrikel % SIZE);
    }
}
```


```
/**
* Einfuehrung in die Softwareentwicklung 2 (ESE2), SS2018
* Vorfuehraufgabe 4: Studentenverwaltung mit Hash Tabelle
* <p>
* HashTableJUnitTest, Junit4 Testklasse für HashTableStudent
* 
* @author Wolfgang Roessl, Technische Hochschule Ingolstadt (THI)
* @version 2018-04-22
*/

import static java.lang.reflect.Modifier.isPrivate;
import static org.junit.Assert.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.lang.reflect.Field;


public class HashTableStudentJUnitTest {

    private static String[] names;
    private static String[] studyCourse;
    private static int[] matrikel;
   
    @Before
    public void setUp() throws Exception {
        names = new String[] {
                "Max Muster",
                "Betina Test",
                "Hans im Glueck",
                "Qwertz"
            };
           
            studyCourse = new String[]{
                    "UXD",
                    "FFI",
                    "EIT",
                    "IF"
            };
           
            matrikel = new int[]{
                12,
                32,
                52,
                72
            };   
    }

    @After
    public void tearDown() throws Exception {
    }

    @Test
    public void testFields(){
        Class<?> clazzHash = HashTableStudent.class;
        for (Field field : clazzHash.getDeclaredFields()) {
            String fieldName = field.getName();
           
            //all fields are private with exception "next"
            int mod = field.getModifiers();
            assertTrue(  "Access level modifier of '" + fieldName
                       + "' should be private !"
                       , isPrivate(mod));
            }
    }
   
    @Test
    public void testInsertDelete() {
       
        HashTableStudent toTest = new HashTableStudent();
        for(int i = 0; i < names.length; i++){
            Student toInsert = new Student(names[i], studyCourse[i], matrikel[i] );
            toTest.insert(toInsert);
        }
       
       
       
        //Student count
        assertEquals("Student count mismatch", names.length, toTest.getStudentCount());
       
        //Test of JUnitTests
        //Student toInsert = new Student("test", "test", 9 );
        //toTest.insert(toInsert);
       
        //collisions test
        Class<?> hashTab = toTest.getClass();
        try{
               java.lang.reflect.Field field = hashTab.getDeclaredField("studArray");
               field.setAccessible(true);
               StudentList[] studList = (StudentList[])field.get(toTest);
              
               //Array Size should be 20
               assertEquals("Array size mismatch", 20, studList.length);
              
               for(int i= 0; i<studList.length ;i++){
                   if(i != 12)
                       assertNull("Arrayposition with index "+i+"shold be null", studList[i]);
                   else{
                       assertEquals( "There should be "+names.length+" collisions at index 12"
                                    , names.length
                                    , studList[12].getSize());
                   }
               }
        }
        catch(Exception e){
            fail("Field with name studArray is missing");
        }
       
        //delete test
        for(int i = 0; i < matrikel.length; i++){
            toTest.delete(matrikel[i]);
        }
       
        assertEquals("HashTable should be empty!",0,toTest.getStudentCount());
       
    }
}
```


----------



## Thallius (25. Mai 2018)

Ohne da jetzt genauer hingesehen zu haben fehlen doch einige Sicherheitsabfragen in deinem Code. Was ist z.B. wen bei insert NULL übergeben wird? Das knallt dann gewaltig. Oder wenn den anderen Methoden ein invalides matrikel übergeben wird?

Gruß

Claus


----------

