Meine Hash-Map ist nicht effizient

Hidiho ihr lieben,

Ich lerne gerade ein wenig Programmieren, da ich ab dem kommenden Semester ziemlich Programmieren muss :(. Zum lernen habe ich mir ein Programm gezogen, dass ich nun zu lernzwecken ein wenig umgestalten mag. Es handelt sich dabei um eine einfache Art des Eliza Programms.

Das Programm reagiert auf die Eingaben des Benutzers und sucht sich dann in vorgegebenen der vorgegebenen Hash-map heraus, was es antworten soll. Das ganze funktioniert auch :), doch die Suche nach dem Schlüsselwort gibt sich recht ineffizient, denn ich muss diese nicht nur bei den einzelnen temps hineinschreiben, sondern auch bei String[] keywords. Diese doppelte Arbeit kann jedoch nicht im Sinne einer Sinnigen Programmierung angenommen werden.

Ich habe nun einfach versucht das ganze wegzulassen, dies gab aber nur einen Fehler und das Programm startete nicht :grr:. Da ich ein Noob mit wenig Ahnung bin, komme ich auf keine sinnige Lösung.

Über hilfreiche und vor allem einfach zu verstehende Antworten würde ich mich freuen :o).

[LEFT]


HashMap<String,String[]> responses = new HashMap<String,String[]>();
    
        String[] temp0={"Könnten Sie das vielleicht ein wenig ausführlicher erklären?",
            "Würden Sie das ein weniger ausführlicher erklären?",
            "Ich kann Ihnen leider nicht ganz folgen. Könnten Sie das ausführlicher erklären?",
            "Ich verstehe das leider nicht, würden Sie es ein weniger ausführlicher erklären?",
            "Ich verstehe Sie nicht."            
    };
    responses.put("NOTFOUND", temp0);

    String[] temp1={"Könnten Sie ein Beispiel dafür nennen?", 
                        "Haben Sie das dafür ein Beispiel?"};    
    responses.put("immer", temp1);

    String[] temp2={"Ist das der wahre Grund?"};
    responses.put("weil", temp2);
        responses.put("wegen", temp2);

    String[] temp3={"Niemals entschuldigen, das ist ein Zeichen von Schwäche."};
    responses.put("es tut mir leid", temp3);
        responses.put("sorry", temp3);
        responses.put("entschudigung", temp3);

    String[] temp4={"Wirklich Sicher scheinen Sie da nicht zu sein."};
    responses.put("vielleicht", temp4);
        responses.put("eventuell", temp4);

    String[] temp5={"Denken Sie das wirklich?"};
    responses.put("ich denke", temp5);

    String[] temp6={"Ich w\u00fcrde es vorziehen, wir blieben beim Sie.",
                        "Wir sind nicht per Du."};
    responses.put("du", temp6);

    String[] temp7={"Warum denken Sie das?",
            "Warum sind Sie davon überzeugt?"};
    responses.put("ja", temp7);
        responses.put("selbstverständlich", temp7);
        responses.put("natürlich", temp7);

    String[] temp8={"Warum nicht?",
            "Warum glaube Sie das nicht?"
                        };
    responses.put("nein", temp8);
        responses.put("auf keinen Fall", temp8);
        responses.put("nee", temp8);
        responses.put("niemals", temp8);

    String[] temp9={"Es tut mir Leid zu hören, dass Sie * sind.",
            "Wie lange sind Sie schon *?",
            "Können Sie sich vorstellen, dass es normal ist * zu sein?",
            "Wie fühlen Sie sich dabei, * zu sein?"
                        };
    responses.put("ich bin", temp9);
    
    String[] temp10={"Erzählen Sie mir mehr über das Gefühl.",
             "Fühlen Sie sich oft *?",
             "Mögen Sie es,sich * zu fühlen?"
                        };
    responses.put("ich fühle mich", temp10);

    String[] temp11={"Erzählen Sie mir mehr über ihre Arbeit.",
             "Wie kommen Sie mit ihrer Arbeit zurecht?",
             "Ist ihre Arbeit wichtig für Sie?"
    };
    responses.put("arbeit", temp11);
    responses.put("arbeiten", temp11);
    responses.put("schaffen", temp11);

    String[] temp12={"Träumen Sie oft davon",
             "Was könnte dieser Traum bedeuten?",
             "Wer taucht ih Ihrem Traum auf?"         
    };
    responses.put("traum", temp12);
    responses.put("albtraum", temp12);
        
        String[] temp13={"Wie kann ich helfen?"
             };
        
    responses.put("hallo", temp13);
        
         
        String[] keywords={"immer","weil","wegen","es tut mir leid", "sorry", 
                            "entschuldigung", "vielleicht", "eventuell", "ich denke", 
                            "du", "ja", "selbstverständlich", "natürlich",
                            "auf keinen Fall", "nein", "nee", "niemals", "ich bin", 
                            "ich fühle mich", "arbeit", "arbeiten", "schaffen", "traum", 
                            "albtraum", "hallo"};


Liebe Grüße

[/LEFT]

Was meinst du genau? Reagiert dein Programm zu langsam beim Auftauchen eines Schlüsselwortes? Das kann ich mir kaum vorstellen… Oder findest du die Art der Programmierung zu umständlich?
Generell hast du hier ein Problem bzw. Programm vorliegen das man beliebig komplex und kompliziert gestalten kann. Diese Umsetzung ist denke ich so ziemlich die einfachste Herangehensweise. Wenn dir das noch zu schwierig ist, oder dir keine Möglichkeit einfällt es anders zu lösen, solltest du dir vielleicht nochmal ein einfachereres Programm zum üben suchen.
Was du mit dem Weglassen gemeint hast, verstehe ich ebenfalls nicht ganz. Was genau hast du weggelassen?

Nein, da könntest du ein HashSet verwenden, musst du aber gar nicht.
Du kannst einfach responses.contains(key) verwenden.
Ausser ich hab dich falsch verstanden…

Wow, schon innerhalb so kurzer Zeit 2 Antworten :D.

Es ist die Art der Programmierung die mir zu umständlich vorkommt.

Beispiel:

String[] temp1 nennt die beiden möglichen Antworten, für das Wort immer:

String[] temp1={"Könnten Sie ein Beispiel dafür nennen?",
                          "Haben Sie das dafür ein Beispiel?"};

Darunter wird das entsprechende Schlüsselwort bezeichnet:

responses.put("immer", temp1);

Doch gefunden wird es erst, wenn es auch in String[] keywords eingetragen wird:

String[] keywords={"immer","weil","wegen","es tut mir leid", "sorry",
                              "entschuldigung", "vielleicht", "eventuell", "ich denke",
                              "du", "ja", "selbstverständlich", "natürlich",
                             "auf keinen Fall", "nein", "nee", "niemals", "ich bin",
                              "ich fühle mich", "arbeit", "arbeiten", "schaffen", "traum",                              "albtraum", "hallo"};

Diese doppelte Eintragerei ist es die mich ein wenig stört. Dies scheint mir ein unsinnige doppelte Arbeit zu sein, die, sollten mehr Worte hinzukommen um das Programm auch wirklich Sinnvoll antworten zu lassen, erheblichen Aufwand verursachen.

Daher denke ich, dass das auch mit nur einem Mal eintragen gehen sollte.:eek:

Wow, schon innerhalb so kurzer Zeit 2 Antworten .

Es ist die Art der Programmierung die mir zu umständlich vorkommt.

Beispiel:
String[] temp1 nennt die beiden möglichen Antworten, für das Wort immer:

String[] temp1={"Könnten Sie ein Beispiel dafür nennen?", "Haben Sie das dafür ein Beispiel?"};

Darunter wird das entsprechende Schlüsselwort bezeichnet:

responses.put("immer", temp1);

Doch gefunden wird es erst, wenn es auch in String[] keywords eingetragen wird:

String[] keywords={"immer","weil","wegen","es tut mir leid", "sorry", "entschuldigung", "vielleicht", 
"eventuell", "ich denke", "du", "ja", "selbstverständlich", "natürlich", "auf keinen Fall", "nein", "nee", "niemals", 
"ich bin", "ich fühle mich", "arbeit", "arbeiten", "schaffen", "traum", "albtraum", "hallo"};

Diese doppelte Eintragerei ist es die mich ein wenig stört. Dies scheint mir ein unsinnige doppelte Arbeit zu sein, die, sollten mehr Worte hinzukommen um das Programm auch wirklich Sinnvoll antworten zu lassen, erheblichen Aufwand verursachen.

Daher denke ich, dass das auch mit nur einem Mal eintragen gehen sollte. :smiley:

„Meine HashMap / -Set ist nicht effizient“
Diese Aussage ist falsch… :wink:
Mus heissen, die Berechnung meiner HashCodes ist nicht effizient. Wenn sich das nicht ändern lässt, ist die Verwendung einer anderen Collection bzw. Map meistens (bis immer) effektiver.

Hmmmm… darum ging es wohl nicht.

Man sieht nicht genau, wo die
HashMap<String,String[]> responses und
String[] keywords
liegen, aber wenn du mal ein compilierbares (!) Stück code posten würdest, wo man in etwa sieht, wie ‘responses’ und ‘keywords’ verwendet werden, könnte man die Sache mit den doppelten Eintragungen sicher einfacher machen. Vielleicht schon GROB durch eine Methode wie

private void addResponse(String keyword, String ... responsePhrases)
{
      ...
}
public class Minion{
    
    
    public static void main(String args[]){
        
        //Initialization
    boolean endloop=false;
    Scanner antwort  = new Scanner(System.in);
    Scanner currentline;
    
    // Begruessung
    System.out.println("Hallo");
    

    // Schleife 
    while (!endloop){
            currentline=new Scanner(antwort.nextLine().toLowerCase());
        if (currentline.findInLine("minion herunterfahren")==null)
        System.out.println(respond(currentline));   //Antwort
        else {                                       
        System.out.println("Auf wiedersehen.");     //Exit
        endloop=true;
                 }
                        }
    }

    
    // Input

    private static String respond(Scanner s){

    HashMap<String,String[]> responses = new HashMap<String,String[]>();
    
        String[] temp0={"Könnten Sie das vielleicht ein wenig ausführlicher erklären?",
            "Würden Sie das ein weniger ausführlicher erklären?",
            "Ich kann Ihnen leider nicht ganz folgen. Könnten Sie das ausführlicher erklären?",
            "Ich verstehe das leider nicht, würden Sie es ein weniger ausführlicher erklären?",
            "Ich verstehe Sie nicht."            
    };
    responses.put("NOTFOUND", temp0);

    String[] temp1={"Könnten Sie ein Beispiel dafür nennen?", 
                        "Haben Sie das dafür ein Beispiel?"};    
    responses.put("immer", temp1);

    String[] temp2={"Ist das der wahre Grund?"};
    responses.put("weil", temp2);
        responses.put("wegen", temp2);

    String[] temp3={"Niemals entschuldigen, das ist ein Zeichen von Schwäche."};
    responses.put("es tut mir leid", temp3);
        responses.put("sorry", temp3);
        responses.put("entschudigung", temp3);

    String[] temp4={"Wirklich Sicher scheinen Sie da nicht zu sein."};
    responses.put("vielleicht", temp4);
        responses.put("eventuell", temp4);

    String[] temp5={"Denken Sie das wirklich?"};
    responses.put("ich denke", temp5);

    String[] temp6={"Ich w\u00fcrde es vorziehen, wir blieben beim Sie.",
                        "Wir sind nicht per Du."};
    responses.put("du", temp6);

    String[] temp7={"Warum denken Sie das?",
            "Warum sind Sie davon überzeugt?"};
    responses.put("ja", temp7);
        responses.put("selbstverständlich", temp7);
        responses.put("natürlich", temp7);

    String[] temp8={"Warum nicht?",
            "Warum glaube Sie das nicht?"
                        };
    responses.put("nein", temp8);
        responses.put("auf keinen Fall", temp8);
        responses.put("nee", temp8);
        responses.put("niemals", temp8);

    String[] temp9={"Es tut mir Leid zu hören, dass Sie * sind.",
            "Wie lange sind Sie schon *?",
            "Können Sie sich vorstellen, dass es normal ist * zu sein?",
            "Wie fühlen Sie sich dabei, * zu sein?"
                        };
    responses.put("ich bin", temp9);
    
    String[] temp10={"Erzählen Sie mir mehr über das Gefühl.",
             "Fühlen Sie sich oft *?",
             "Mögen Sie es,sich * zu fühlen?"
                        };
    responses.put("ich fühle mich", temp10);

    String[] temp11={"Erzählen Sie mir mehr über ihre Arbeit.",
             "Wie kommen Sie mit ihrer Arbeit zurecht?",
             "Ist ihre Arbeit wichtig für Sie?"
    };
    responses.put("arbeit", temp11);
    responses.put("arbeiten", temp11);
    responses.put("schaffen", temp11);

    String[] temp12={"Träumen Sie oft davon",
             "Was könnte dieser Traum bedeuten?",
             "Wer taucht ih Ihrem Traum auf?"         
    };
    responses.put("traum", temp12);
    responses.put("albtraum", temp12);
        
        String[] temp13={"Wie kann ich helfen?"
             };
        
    responses.put("hallo", temp13);
        
         
        String[] keywords={"immer","weil","wegen","es tut mir leid", "sorry", 
                            "entschuldigung", "vielleicht", "eventuell", "ich denke", 
                            "du", "ja", "selbstverständlich", "natürlich",
                            "auf keinen Fall", "nein", "nee", "niemals", "ich bin", 
                            "ich fühle mich", "arbeit", "arbeiten", "schaffen", "traum", 
                            "albtraum", "hallo"};
    
    
    //Variablen
    
        String response="";
    String[] response_array={""};
    boolean found=false;
    String currentkeyword="";
    

    /* Loop through keywords */
    for(int i=0; i<keywords.length;i++){
        if ((s.findInLine(currentkeyword=(String)keywords**)!=null) 
        && (responses.get(currentkeyword)!=null)){
        found=true;
        response_array=(String[])responses.get(currentkeyword);
        response=response_array[(int)((response_array.length-1)*
                         Math.random())];
    
        if (response.indexOf('*')!=-1){
            String remaining_input;
            if (s.hasNext() && 
            (remaining_input=s.nextLine().trim())!=null){
            response = response.substring(0,response.indexOf('*'))+
                remaining_input
                .substring(0,remaining_input.length()-1)
                + remaining_input
                .substring(remaining_input.length()-1,
                       remaining_input.length())
                .replaceAll("[^A-Za-z]", "") +
                response.substring(response.indexOf('*')+1, 
                           response.length());
            response=response.trim();
            }
            else
            response=response.replaceAll("
[li]","");
[/li]        }
        }
    }
    
    // Kein Schluesselwort
    if (!found){
        response_array=(String[])responses.get("NOTFOUND");
        response=response_array[(int)((response_array.length-1)*
                     Math.random())];
    }
    return response;
    }    
}

Erstmal ganz kurz: Durch sowas wie

        /* Loop through keywords */
        for (String currentkeyword : responses.keySet())
        {
        ....
        }

könnte der keyword-Array schon wegfallen.

Ansonsten gäb’s da einige Verbesserungsmöglichkeiten, angefangen damit, dass das die responses nicht bei jedem Methodenaufruf immer neu aufgebaut werden sollten…

Wenn ich das richtig verstanden habe, gibt es n Schlüsselwörter, die m Antwort-Sätzen zugeordnet werden. Für mich riecht sowas nach einem Objekt:```public class Response{
private List keywords = new ArrayList();
private List responses = new ArrayList();

public void List getKeywords(){ … }
public void addKeyword(String keyword){ … }
public void addResponse(String response){ … }
}```
Deine “Hauptklasse” nimmt dann Response-Objekte entgegen, und legt diese unter jedem ihrer Keywords in die HashMap. Wenn du dann noch eine Methode “getRandomResponse()” für die Klasse Response schreibst, musst du bei einer Eingaben nur nach der Response-Klasse für dein Schlüsselwort suchen und diese Methode aufrufen.

Ohne das alles im Detail gelesen zu haben: new HashMap<String,String[]>() schreit danach, durch eine echte Multimap (z.B. von Guava) ersetzt zu werden.

[QUOTE=Landei]Ohne das alles im Detail gelesen zu haben: new HashMap<String,String[]>() schreit danach, durch eine echte Multimap (z.B. von Guava) ersetzt zu werden.[/QUOTE]Naja, man muss sich ja nicht gleich eine externe Bibliothek ans Bein binden, nur weil man mal mehr als einen Wert für einen Schlüssel abspeichert. :wink:

was heisst „ans Bein binden“ - warum sollte man sich die Muehe machen und etwas nachbauen, was woanders schon gut umgesetzt ist?!

Da es ein Projekt zum lernen ist, sollte/kann man sich die Mühe machen :slight_smile:
Umgesetzt sind so viele Sachen schon, da müsste man kaum noch was programmieren ^^

ja ne is klar… Eins der wichtigsten Dinge die ein Entwickler frueh lernen sollte ist das Rad nicht neu zu erfinden.

Ich geb dir aber recht, fuers anfaengliche Cowboy programmieren kann man es auch ohne machen

OT:
Ich glaub über die sinnvolle Nutzung von gute Bibliotheken brauchen wir nicht diskutieren :wink:

Vielen Danke für die vielen Meldungen.

Ich denke es ist wohl das sinnigste noch mal von vorne anzufangen anstatt mich durch den mittlerweile nicht mehr sinnigen Code zu wühlen… :(.

Ich habe daher noch mal von vorne angefangen. Daher habe ich gerade das Basic eingebaut bzw. versucht. Also aus der Eingabe ich bin hunrig. soll warum sind sie hunrig? werden Doch anstatt das Wort einzugeben zeigt mir das Programm die Speicheradresse an. Woran liegt das?

[LEFT]```
package Gui;

import java.util.*;

/**
*

  • @author kanexo
    */
    public class Minion_Main {

    public static void main(String args[]){

    //Begruessung
    System.out.println(“Hallo.”);

    //Initialisierung
    boolean beenden=false;
    Scanner eingabe = new Scanner(System.in);

    //System.out.println(antwort(eingabe));

    while (!beenden){

         Scanner aktuell=new Scanner(eingabe.nextLine().toLowerCase());
     if (aktuell.findInLine("minion herunterfahren")==null)
     System.out.println(antwort(aktuell));
     else {                                       
     System.out.println("Auf wiedersehen.");
     beenden=true;
              }
    

    }

    }

    private static String antwort(Scanner aktuell){

     String antwort= ("Warum sind Sie" + aktuell + "?");
     antwort=antwort.replaceAll("[ich bin]","");
                    
     return antwort;
    

    }

}

weil du den Scanner an sich ausgibst…

du musst natuerlich die Antwort vom Scanner lesen

Scanner aktuell=new Scanner(eingabe.nextLine().toLowerCase());

ist auch nicht toll. Warum einen neuen Scanner?

Hallo.

Warum ich das so gemacht habe? Weil ich es nicht besser weiss…:o

Wie wäre es denn am Sinnvollsten?