Meine Hash-Map ist nicht effizient


#5

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:


#6

“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.


#7

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)
{
      ...
}

#8
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;
    }    
}

#9

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…


#10

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.


Generics gehen bei "Fix formatting post-migration: Javas, rmCRs" kaputt
#11

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.


#12

[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:


#13

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


#14

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 ^^


#15

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


#16

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


#17

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;
    

    }

}


#18

weil du den Scanner an sich ausgibst…

du musst natuerlich die Antwort vom Scanner lesen


#19

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

ist auch nicht toll. Warum einen neuen Scanner?


#20

Hallo.

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

Wie wäre es denn am Sinnvollsten?


#21

Kannst du bitte linksbündig schreiben?

Weil man die erzeugte scanner-Instanz einfach nochmal verwenden kann.

Das Problem ist, dass du glaube ich dir noch nicht den Weg überlegt hast den du gehen möchtest.

Was du machst:

Scanner anlegen. Ok
Dann der Fehler mit der eingabe, denke ich korrigierst du.
Dann instantiierst du einen neuen Scanner mit einem String der aus einem anderen Scanner kommt. Woher kommt dieses Konstrukt? Und vor allem, was soll da rauskommen?

Lies doch einfach nextLine in eine String variable und dann schau mal weiter


#22

du meinst wohl eher
String s = eingabe.nextLine().toLowerCase();


#23

Wieso schreibst du immer zentriert ich finde das extrem anstrengend zu lesen :frowning:

Das beste wäre wenn du ganz simpel beginnst

   public static void main(String[] args) throws IOException
  {
    InputStreamReader isr = new InputStreamReader(System.in);
    BufferedReader br = new BufferedReader(isr);
    System.out.print("Gib was ein: ");
    String eingabe = br.readLine();
    System.out.println("Du hast " + eingabe + " eingegeben.");
  }```


Edit: Hier http://www.javabeginners.de/Ein-_und_Ausgabe/Scanner.php ist auch ein gutes Beispiel, inkl einer while Schleife, die solange läuft bis man q drückt.

#24

Ich danke Dir, für Deine Antwort, und schreibe natürlich auch gerne Linksbündig, falls das lieber gesehen wird. :smiley:

Leider kann ich mit Deiner Antwort immer noch nicht viel anfangen. Kannst Du mir ein Beispiel geben, wie ich es besser machen könnte?