ArrayList suche

ich hab eine ArrayList


ArrayList<Verein> list = new ArrayList<Verein>();


public class Verein(){
String name;
int mitglieder;
}

nun will ich eine Methode schreiben umd die Liste z.B. nach dem Namen durchsuchen.
Kann mir jemand helfen wie ich das machen kann?

Guck mal hier: http://forum.byte-welt.net/showpost.php?p=8014&postcount=16
Das entspricht in etwa der Methode suche() in der Klasse Getraenke.

ist dazu nicht eine sortierung der ArrayListe notwendig? Vll hab ich da auch noch was falsch im Hinterkopf hängen…

Nein. Es wird die Liste so lange nach dem übergebenen Namen durchsucht, bis in einem Objekt ein gleicher Name gefunden wurde. Wenn ein der übergebene Name gefunden wurde, wird das Objekt für die weitere Verarbeitung zurück gegeben. Wenn der Name nicht in einem Objekt der Liste gefunden wurde, wird null (nichts) zurückgegeben.
Eine Sortierung ändert an der Funktion der Methode nichts.

Es gibt “Collections.sort” und es gibt “Comparable” bzw. “Comparator”. Warum gibts nicht “Findable” und “Collections.find”?

So, ich hab mal ne allgemeine Version zusammengefrickelt:

	
  public <T> ArrayList<T> find(Collection<T> coll, Map<String, ?> find) throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException {
    return find(coll, find, true);
  }

  public <T> ArrayList<T> find(Collection<T> coll, Map<String, ?> find, boolean andMatch) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException {

    if (coll.size() < 1) {
      return new ArrayList<T>();
    }
    @SuppressWarnings("unchecked")
    Class<T> cls = (Class<T>)coll.toArray()[0].getClass();
    ArrayList<T> result = new ArrayList<T>();
    Field[] fields = new Field[find.size()];
    int pos = 0;
    for (String s : find.keySet()) {
      fields[pos] = cls.getDeclaredField(s);
      fields[pos++].setAccessible(true);
    }
    boolean match = true;
    for (T t : coll) {
      match = andMatch;
      for (Field f : fields) {
        if (andMatch && !f.get(t).equals(find.get(f.getName()))) {
          match = false;
          break;
        }
        else if (!andMatch && f.get(t).equals(find.get(f.getName()))) {
          match = true;
          break;
        }
      }
      if (match) {
        result.add(t);
      }
    }
    return result;
  }
}```

Und ne Main-Methode zum Testen:

```public class FindMain {

  public static void main(String[] args) throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException {

    Finder finder = new Finder();

    class Verein {

      public Verein(String name, int mitglieder) {
        this.name = name;
        this.mitglieder = mitglieder;
      }

      private String name;
      private int mitglieder;

      public String toString() {
        return this.name + " " + this.mitglieder;
      }
    }

    ArrayList<Verein> vereine = new ArrayList<Verein>();
    vereine.add(new Verein("Byte-Welt.de", 500));
    vereine.add(new Verein("Java-Blog-Buch.de", 4));
    vereine.add(new Verein("Deutschland", 80000000));
    vereine.add(new Verein("Verein", 500));

    HashMap<String, Object> find = new HashMap<String, Object>();
    find.put("mitglieder", 500);

    List<Verein> result = finder.find(vereine, find);

    System.out.println(result.size());
    for (Verein v : result) {
      System.out.println(v);
    }

    find.put("name", "Byte-Welt.de");
    result = finder.find(vereine, find);
    System.out.println(result.size());
    for (Verein v : result) {
      System.out.println(v);
    }

    result = finder.find(vereine, find, false);
    System.out.println(result.size());
    for (Verein v : result) {
      System.out.println(v);
    }
  }
}```

Ist jetzt nur schnell zusammengeschrieben und müsste meiner Ansicht nach funktionieren. Code könnte evtl. noch optimiert werden. Feedback ist gerne gesehen!

du hast dir zwar viel Mühe gegeen, allerdings kann ich damit ehrichgesagt nichts anfangen.

Das problem war doch eine ArrayList nach etwas zu durchsuchen…

geht das auch in weniger Zeilen und etwas…Anfängerfreundlicher?

OK,

Kopiere die Klasse Finder und speichere sie in deinem Projekt ab.

Alles, was du nun noch machen musst:

Du erzeugst eine Map<String, Object> (z. B. eine HashMap). In diese fügst du ganz normal Key-Value-Paare ein. Key ist der Name des Attributs/Feldes im Verein und die Value der erwartete Wert. Diese Map übergibst du dann mitsamt deiner ArrayList dem Finder. Schon bekommst du eine ArrayListe zurück, die alle Treffer beinhaltet.

Für dich z. B.:

// vereine mit Vereinen füllen
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("name", "Ortsverein"); // Du möchtest nach den Vereinen suchen, deren Attribut "name" gleich "Ortsverein" ist
ArrayList<Verein> ergebnis = new Finder().find(vereine, map);```

Verstanden?

Für alle, denen ein equals-Vergleich von Attributen der Klassen nicht ausreicht, gibts die Methode find mit den Parametern Collection coll und FindWith. FindWith ist ein nested static Interface, bei dem in der match-Methode überprüft werden soll, ob das übergebene Objekt den Suchkriterien entspricht.


  public <T> ArrayList<T> find(Collection<T> coll, Map<String, ?> find) throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException {
    return find(coll, find, true);
  }

  public <T> ArrayList<T> find(Collection<T> coll, Map<String, ?> find, boolean andMatch) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException {

    if (coll.size() < 1) {
      return new ArrayList<T>();
    }
    @SuppressWarnings("unchecked")
    Class<T> cls = (Class<T>)coll.toArray()[0].getClass();
    ArrayList<T> result = new ArrayList<T>();
    Field[] fields = new Field[find.size()];
    int pos = 0;
    for (String s : find.keySet()) {
      fields[pos] = cls.getDeclaredField(s);
      fields[pos++].setAccessible(true);
    }
    boolean match = true;
    for (T t : coll) {
      match = andMatch;
      for (Field f : fields) {
        if (andMatch && !f.get(t).equals(find.get(f.getName()))) {
          match = false;
          break;
        }
        else if (!andMatch && f.get(t).equals(find.get(f.getName()))) {
          match = true;
          break;
        }
      }
      if (match) {
        result.add(t);
      }
    }
    return result;
  }

  public <T> ArrayList<T> find(Collection<T> coll, FindWhith<T> find) {

    ArrayList<T> result = new ArrayList<T>();
    for (T t : coll) {
      if (find.match(t)) {
        result.add(t);
      }
    }
    return result;
  }

  public static interface FindWith<T> {
    public boolean match(T check);
  }
}```

```public class FinderMain {

  public static void main(String[] args) throws IllegalArgumentException, SecurityException, IllegalAccessException, NoSuchFieldException {

    Finder finder = new Finder();

    class Verein {

      public Verein(String name, int mitglieder) {
        this.name = name;
        this.mitglieder = mitglieder;
      }

      private String name;
      private int mitglieder;

      public int getMitglieder() {
        return this.mitglieder;
      }

      public String toString() {
        return this.name + " " + this.mitglieder;
      }
    }

    ArrayList<Verein> vereine = new ArrayList<Verein>();
    vereine.add(new Verein("Byte-Welt.de", 500));
    vereine.add(new Verein("Java-Blog-Buch.de", 4));
    vereine.add(new Verein("Deutschland", 80000000));
    vereine.add(new Verein("Verein", 500));

    HashMap<String, Object> find = new HashMap<String, Object>();
    find.put("mitglieder", 500);

    List<Verein> result = finder.find(vereine, find);

    System.out.println(result.size());
    for (Verein v : result) {
      System.out.println(v);
    }

    find.put("name", "Byte-Welt.de");
    result = finder.find(vereine, find);
    System.out.println(result.size());
    for (Verein v : result) {
      System.out.println(v);
    }

    result = finder.find(vereine, find, false);
    System.out.println(result.size());
    for (Verein v : result) {
      System.out.println(v);
    }

    Finder.FindWith<Verein> fw = new Finder.FindWith<Verein>() {

      @Override
      public boolean match(Verein check) {
        return check.getMitglieder() > 450;
      }
    };

    result = finder.find(vereine, fw);
    System.out.println(result.size());
    for (Verein v : result) {
      System.out.println(v);
    }
  }
}```

ich bereite mich gerade auf eine Projektarbeit vor, deshalb bringt mir Code kopieren nicht viel.

Ich habe eine ArrayList und diese Beinhaltetet nochmal eine ArrayListe.

Meine Suchklasse kann einmal nach dem Namen suchen oder nach Objekten der 2ten ArrayList

kannst du mir ein Tipp geben wie man das am besten umsetzen kann?!

Hallo Unregistriert,

meine Lösung sollte vielmehr als allgemeine Lösung für dieses Problem angesehen werden. Für dich wird es einfacher sein, das von LeX umzusetzen. Wo liegen denn da deine Probleme?

Mein Prolbem:

  • Suchkriterien einbauen
  • ArrayList in ArrayList druchsuchen…

ich denke das ist kein Hexenwerk…aber ich bin nach am Anfang meiner Java Karriere…

Ich hoffe dieses Codebespiel hilft dir mehr weiter. Ich habe es bewusst so einfach wie möglich gehalten:


public class Verein {
	String name;
	int mitglieder; 
	
	public Verein( String name, int mitglieder ) {
		this.name = name;
		this.mitglieder = mitglieder;
	}
	
	public static void main( String[] args ) {
		ArrayList<Verein> vereinsliste = new ArrayList<Verein>();
		vereinsliste.add( new Verein("AKMA", 1509) );
		vereinsliste.add( new Verein("ASKÖ", 2345) );
		
		Verein gesucht = getVerein( vereinsliste, "AKMA" );
		
		System.out.println( "Gesuchter Verein " + gesucht.name + " hat " + gesucht.mitglieder + " Mitglieder." );
	}
	
	public static Verein getVerein( ArrayList<Verein> list, String name ) {
		for ( Verein tmp : list ) {
			if ( tmp.name.equals(name) ) {
				return tmp;
			}
		}
		
		return null;
	}
}```

Das mit den verschachtelten ArrayList's ist hier aber noch nicht berücksichtigt. (Dieser Programmierstil wie oben ist übrigens ganz pfui, ist wirklich nur zur Veranschaulichung ^^)

Meiner Meinung nach, sind verschachtelte ArrayListen sogar Designfehler.

Vorsicht mit solchen Pauschalurteilen, LeX… :slight_smile:

Ebenius

[QUOTE=Ebenius]Vorsicht mit solchen Pauschalurteilen, LeX… :slight_smile:

Ebenius[/QUOTE]

Bei nem selbst ernannten Anfänger gehe ich aber mal davon aus, dass LeX recht hat.

Warum Designfehler? Sind HashMaps die Eleganterer bzw. das einzig richtige?

Kommt auf den Anwendungsfall an. Meistens braucht man auch nicht mal eine (Hash)Map. Welche Datenstruktur möchtest du denn mit deiner Liste in der Liste darstellen?

Angenommen ich würde für die “Bestandsaufnahe” eine Hashmap verwenden.

als Key wird der String name verwendet
für Value werden Vereine genommen.


public class Verwaltung{

HashMap<String, Verein> vereine = new HashMap<String, Verein>();
}

was würde dann in der Klasser Verein stehen wenn dort ursprünglich eine ArrayList für Mitglieder drin war?

mommentan werden die Daten einfach unsortiert in einer ArrayList gehalten