Verkettete Objektliste Funktion "enthaelt"

pf20

Neues Mitglied
Hallo Leute,
Als ich vor kurzem noch zur Schule ging, haben wir über Objektorientierte Programmierung in Java gesprochen. Darunter auch Datenstrukturen wie der Verkettete Liste. Ich programmiere mit Eclipse. Alle Namen in den Codeschnipseln sind frei erfunden! Hier ein paar Codeschnipsel bevor ich das Problem erläutern kann:
Die Steuerungsklasse:
Java:
public class Steuerung {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Kontakt meinKontakt;
        VerketteteListe<Kontakt> MeineKontaktListe = new VerketteteListe<Kontakt>();

        MeineKontaktListe.anhaengen( new Kontakt( "Schmitt", "Holger", "H.Schmitt@web.de", "0711 88888"  ) );
        MeineKontaktListe.anhaengen( new Kontakt( "Müller",  "Klaus", "K.Mueller@web.de",  "0711 0815"   ) );
        MeineKontaktListe.anhaengen( new Kontakt( "Maier",   "Fritz", "F.Maier@gmail.com", "0711 007"    ) );
        MeineKontaktListe.anhaengen( new Kontakt( "Schmidt", "Franz", "F.Schmidt@web.de",  "0711 318810" ) );
        MeineKontaktListe.anhaengen( new Kontakt( "Wolf",    "Bernd", "B.Wolf@gmail.com",  "0711 319910" ) );
        
        int anzahlKontakte = MeineKontaktListe.anzahl_elemente();
        for ( int i=0; i < anzahlKontakte; i++ ) {
            meinKontakt = MeineKontaktListe.inhalt(i);
            meinKontakt.ausgebenKontakt();
        }
        if (MeineKontaktListe.enthaelt(Kontakt("*", "Franz", "*", "*"))) {
            System.out.println("In der Liste ist jemand mit dem Vornamen Franz enthalten");
        }
    }

}
Hier der Wichtigste Ausschnitt aus der Klasse der Verketteten Liste:
Java:
Typ inhalt (int pIndex) {
        
        if( pIndex < 0 ) { return null; }
        
        Knoten<Typ> meinKnoten = erster;
        for ( int i = 0; i < pIndex; i++ ) {
            if ( meinKnoten == null ) { return null; }
            meinKnoten = meinKnoten.gibNaechsten();
        }
        
        if ( meinKnoten == null ) { return null; }
        
        return (Typ)meinKnoten.gibInhalt();
    } // end of inhalt
Und die Funktion "Enthaelt" aus der Klasse VerketteteListe:
Java:
boolean enthaelt ( Typ pInhalt ) {
        
        Knoten<Typ> meinKnoten = erster;
        while (meinKnoten != null) {
            
            if ( (Typ)meinKnoten.gibInhalt() == (Typ)pInhalt ) {
                return true;
            }
            meinKnoten = meinKnoten.gibNaechsten();
        }
        return false;
    } // end of enthaelt
Hier die Klasse des Knotens (Kettenglied der Verketteten Liste):
Java:
public class Knoten<Typ> {
    private Typ inhalt;
    private Knoten<Typ> naechster;

    Knoten( Typ pInhalt ) {
        inhalt = pInhalt;
    }
    
    void setzeNaechsten( Knoten<Typ> pKn ) {
        naechster = pKn;
    }

    Knoten<Typ> gibNaechsten() {
        return naechster;
    }
    
    void setzeInhalt( Typ pInhalt ) {
        inhalt = pInhalt;
    }
    
    Typ gibInhalt() {
        return (Typ)inhalt;
    }

}
Und zu guter letzt die Klasse Kontakt:

Java:
public class Kontakt {
    String aName;
    String aVorname;
    String aEMail;
    String aTelefon;
    
    public Kontakt ( String pName, String pVorname, String pEMail, String pTelefon ) {
        aName    = pName;
        aVorname = pVorname;
        aEMail   = pEMail;
        aTelefon = pTelefon;
    }


}
Hier mein Problem: Ich möchte von der Steuerungsklasse aus die Funktion enthaelt() aufrufen, um abzufragen, ob in der Liste jemand mit dem Vornamen "Franz" enthalten ist. Selbst wenn ich als Übergabeparameter einen neuen Kontakt anlege und Kontakt-Objektattribute genau abschreibe, gibt sie trotzdem ein falsch zurück. Sie gibt nur ein true zurück, wenn ich die Variable meinKontakt mit dem pointer auf einen Index als Übergabeparameter. Also z. B. MeineKontaktListe.enthaelt(MeinKontakt.inhalt(4));.Aber das ist ja kein richtiges benutzen der enthaelt-funktion. Wie lautet also die richtige Syntax, um abzufragen, ob in der Liste ein bestimmter Kontakt enthalten ist?
 
Referenz-Typen werden nicht mit == verglichen.

Der Vergleich mit == bei Referenzen prüft nicht den Inhalt sondern nur die Referenz und da es zwei Objekte sind, ist es nicht gleich.

Was du alsbald willst ist die Methode equals die du in deiner Klasse dann überschreiben musst.
 
Und das geht in Eclipse recht bequem über das Menü mit "Source" > "Generate hashCode() and equals()...", wenn du in der betreffenden Klasse bist.
 
Wobei das so auch nicht ausreicht. Der TE möchte anscheinend auch nach nur Teilen suchen bzw. mit Wildcards. Das macht es relativ komplex.

Man kann die equals Methode so schreiben, dass Wildcards beachtet werden: Das erfüllt dann zwar diese Anforderung, aber es entspricht nicht mehr dem Vertrag, der gelten sollte bei equals. Dadurch verhält sich die Methode nicht mehr so wie erwartet.

Eine Möglichkeit wäre dann ggf, dass man eine Filter Klasse schreibt. Also sowas wie ein KontaktFVO (FVO: Filter Value Object).Diese enthält dann z.B. alle Elemente von Kontakt als Optional. Das wäre hier dann ggf. etwas wie:
Java:
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
public class KontaktFVO {
    @Builder.Default
    Optional<String> aName = Optional.empty();
    @Builder.Default
    Optional<String> aVorname = Optional.empty();
    @Builder.Default
    Optional<String> aEMail = Optional.empty();
    @Builder.Default
    Optional<String> aTelefon = Optional.empty();

    public boolean appliesTo(Kontakt contact ) {
        return
                (aName.isEmpty() || aName.get().equals(contact.getAName())) &&
                (aVorname.isEmpty() || aVorname.get().equals(contact.getAVorname())) &&
                (aEMail.isEmpty() || aEMail.get().equals(contact.getAEMail())) &&
                (aTelefon.isEmpty() || aTelefon.get().equals(contact.getATelefon()));
    }
}

Aber der TE hat eine generische Liste. Da haben wir also nur ein generisches Typ. Da muss man dann sowas noch einbauen. Dazu kann dann ein Interface dienen:
Filter<T> hat eine Methode boolean appliesTo(T).
Und die Methode enthaelt erwartet dann als Parameter natürlich ein Filter<Typ>:

Java:
    boolean enthaelt ( Filter<Typ> filter ) {
        if (filter == null) {
            return false;
        }
        
        Knoten<Typ> meinKnoten = erster;
        while (meinKnoten != null) {
            if ( filter.appliesTo(meinKnoten.gibInhalt()) {
                return true;
            }
            meinKnoten = meinKnoten.gibNaechsten();
        }
        return false;
    } // end of enthaelt

Natürlich muss die FVO Klasse dann Filter<> implementieren, also einen Kopf haben wie:
public class KontaktFVO implements Filter<Kontakt> {

Und dann nutzt Du halt nur noch etwas wie:

Java:
        KontaktFVO filter = KontaktFVO.builder()
            .aVorname("Franz")
            .build();
        if (MeineKontaktListe.enthaelt(filter)) {
            System.out.println("In der Liste ist jemand mit dem Vornamen Franz enthalten");
        }

Das wäre eine Möglichkeit, wie man sowas bauen umsetzen könnte. Wichtig ist hier natürlich: Wir haben jetzt keine Wildcards unterstützt. Es werden lediglich nur einzelne Werte angegeben und diese müssen dann natürlich 1:1 vorhanden sein.

Das einfach einmal als ausführliche Sichtweise, wie so eine Anforderung umgesetzt werden könnte, auch wenn ich glaube, dass es dem TE nicht wirklich hilft.
 

Zurück
Oben