LazyTree: Eine einfache Baum-Implementierung für Java

Heute mal keine Rocket Science, sondern ein bisschen Grundlagen. Als mich neulich ein Kollege danach fragte musste ich feststellen, doch tatsächlich noch nie eine Datenstruktur für Bäume in Java benötigt zu haben. Die Collections API enthält, obwohl sie intern durchaus Bäume nutzt, offensichtlich keine dedizierte Schnittstelle für sie. Und so schnell hatte ich eine kleine Kata.

Es geht hier lediglich um eine schnell erstellte, einfach zu nutzende Implementierung, die keine Sonderfälle wie Binär- oder balancierte Bäume berücksicht. Zur Verwaltung verwendet sie eine Standard-Liste aus dem util-Paket. Denn so gesehen ist ein Baum nichts anderes als ein Kompositorium aus Knoten; jeder Knoten kennt einen Datensatz, seinen Eltern-Knoten und eine Menge Kind-Knoten. Wenn wir von “dem Baum” sprechen, meinen wir letztendlich einen bestimmten Wurzelknoten.

Daraus folgend könnte der Rumpf einer Knoten-Klasse und ihre Felder so aussehen:

/**
 * Eine leichtgewichtige Baumstruktur.
 * @author kaeff
 *
 * @param  Datentyp des Baums
 */
public class Node<T> implements Iterable<T>{
	private List<Node<T>> childNodes = new ArrayList<Node<T>>();
	private T data;
	private Node parent;
}

Da wir es quasi mit einem Paradebeispiel für die Nutzung von Generics zu tun haben, bleibt auch die Bindung an einen konkreten Nutzdatentyp konfigurierbar.

Eine diskussionswürdige Frage entsteht im Zusammenhang mit der Verwaltung der Kindknoten: Ist der Baum eine Spezialisierung der Liste oder verwalten wir dafür eine interne Liste? Letzteres erscheint mehrfach sinnvoll:

  • Eine Ableitung würde den Schnittstellenvertrag von der Liste brechen, denn Listen und Bäume sind unterschiedliche Entitäten
  • Die Wahl der konkreten Listen-Realisierung bleibt konfigurierbar (Dies ist hier im Beispiel jedoch nicht explizit berücksichtigt)
  • Durch die Komposition können wir die Komplexität der Liste verstecken

Nachteilig ist lediglich die Entstehung von Boilerplate-Code durch die nötigen Delegationen an das Listen-Feld. Konkret wären das die folgenden grundlegenden Operationen auf der Kindknoten-Menge:

/**
 * Nimmt einen Knoten als Kind auf, ohne childNodes hinzuzufügen
 * @param e Der neue Kind-Knoten
 */
protected void adopt(Node<T> e) {
  if (e.getParent() == this)
    e.setParent(this);
}

/**
 * Entlässt einen Knoten als Kind, ohne ihn aus childNodes zu entfernen
 * @param o Der freizugebende Kind-Knoten
 */
protected void orphan(Object o) {
  if ((o instanceof Node<?>) && (((Node<?>) o).getParent() == this))
    ((Node<?>) o).setParent(null);
}

public boolean add(Node<T> e) {
  adopt(e);
  return childNodes.add(e);
}

public Node<T> remove(int index) {
  orphan(childNodes.get(index));
  return childNodes.remove(index);
}

public boolean remove(Object o) {
  orphan(o);
  return childNodes.remove(o);
}

public boolean addAll(Collection<? extends Node<T>> c) {
  for (Node<T> n : c)
    adopt(n);
  return childNodes.addAll(c);
}

public boolean addAll(int index, Collection<? extends Node<T>> c) {
  for (Node<T> n : c)
    adopt(n);
  return childNodes.addAll(index, c);
}

public Iterator<Node<T>> iterator() {
  return childNodes.iterator();
}

Die Benennung der Methoden orientiert sich an denen des List-Interfaces; um genauer zu sein würden sich z.B. anstattt add und remove auch addChild bzw. removeChild anbieten. Die Methoden adopt bzw. orphan sind zum Aufnehmen bzw. Freigeben von Kindknoten vorgesehen, jedoch lediglich auf der Ebene der Baum-Logik und nicht auf Ebene der childNodes-Listenverwaltung. In ihnen wird lediglich die parent-Eigenschaft des neuen bzw. alten Kindknotens verwaltet. Das Iterable-Interface implementiert die Klasse aus Convenience-Gründen.

Folgende Testklasse demonstriert die Nutzung der Node-Klasse:

public class TreeTest {

    public static void main(String[] args) {
        Node<String> root = new Node<String>("Root");
        Node<String> n1 = new Node<String>("Hallo");
        Node<String> n2 = new Node<String>("Liebe");
        Node<String> n3 = new Node<String>("Welt");
        root.add(n1);
        n1.add(n2);
        root.add(n3);

        printTree(root);
    }

    private static void printTree(Node n1) {
        printTree(n1, 0);
    }

    private static void printTree(Node n1, int intend) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < intend; i++)
             sb.append(" ");
        sb.append("--> '" + n1.getData().toString() + "'");
        System.out.println(sb.toString());
        for (Node child : n1)
            printTree(child, intend + 2);
    }

}

Was man noch tun könnte:

  • Interface extrahieren: Node wird NodeListImpl, die relevanten Methoden-Rümpfe kommen in die Schnittstelle Node
  • Weitere Operationen auf der Kindknoten-Liste hinzufügen und delegieren

Den kompletten Quellcode gibt’s bei Bitbucket.

Veröffentlicht unter Coding | Hinterlasse einen Kommentar

Kurznotiz zu Google Instant

Das große G macht’s mal wieder: Der nebenstehende Cartoon verdeutlicht ganz gut, was gute Software von wirklich nützlicher unterscheidet. Wer glaubt, dass die Einfachheit der berühmten Suchmaschinen-Startseite das höchste Maß der Dinge ist, wird durch das neue Google Instant eines Besseren belehrt. Die Funktion führt bereits während der Eingabe Suchanfragen im Hintergrund durch und zeigt vorläufige Ergebnisse.

Die konsequente Weiterentwicklung der Suchwort-Vorschlagsliste macht somit quasi den Suchbutton überflüssig und reduziert die Anzahl der nötigen GUI-Elemente auf 1. Glaubt man seinem Erfinder, so soll das Feature jede Sekunde 11 Stunden Zeit einsparen, geht man von 2 bis 5 Sekunden Verbesserung pro Anfrage aus.

Die Kombination aus einer Oberfläche, die stets den nächsten Schritt des Benutzers zu erraten versucht und wohl einigen Stunden an Optimierungsarbeit auf Backend- und Transportebene taugt wohl als Vorzeigebeispiel für gutes Usability Engineerings: Den Nutzer interessiert nicht, wie etwas gemacht wird, sondern dass es funktioniert.

Veröffentlicht unter Web-Anwendungen | 2 Kommentare

WordPress 3.0 Plugins und Tipps

WordPress 3.0 ist ja nun seit einiger Zeit verfügbar, Version 3.0.1 ließ ebenfalls nicht lange auf sich warten. Zeit für ein paar Plugin-Empfehlungen und Tipps, die auch hier zum Einsatz kommen.

WPTouch

Dieses nützliche Add-On verleiht einem WordPress-Blog mit verschwindend geringem Aufwand ein zusätzliches Theme für Smartphones. Die Oberfläche besticht durch speziell auf mobile Surfer ausgerichtete Lesbarkeit und Bedienung und kommt obendrein mit netten Icons und Animationen daher. Unbedingt installieren und ausprobieren.

WordPress für Android

Kein Plugin, aber trotzdem eine sinnvolle Erweiterung des Werkzeuggürtels für Blogger ist die neue  WordPress-App für Android-Smartphones. Neben dem Moderieren von Kommentaren ermöglicht sie auch die Bearbeitung und Veröffentlichung von Artikeln und Seiten inklusive Upload-Funktionalität für Bilder und Videos. Nutzern der Besucherstatistik von WordPress.com stehen die Auswertungen hiermit auch mobil zur Verfügung.

Die App kann sowohl gehostete WordPress.com-Blogs, als auch selbst verwaltete Installationen ansprechen. Kommt es bei letzteren anfangs zu Verbindungsproblemen, so liegt das wahrscheinlich an der standardmäßig deaktivierten XML-RPC-Schnittstelle. Diese lässt sich fix unter Einstellungen -> Schreiben aktivieren.

WordPress 3.0 Multi-Site

Unter den tollen Neuerungen des dritten WordPress-Majors schätze ich vor allem das Mutli Site-Feature. Die Standard- und MU-Versionen, welche bisher getrennten Entwicklungszweigen folgten, wurden mit 3.0 zusammengeführt. Ist das Feature einmal aktiviert, lassen sich unzählige verschiedene Blogs mit nur einer Installation aufsetzten. Da sich die Blogs die verfügbaren Themes, Plugins und Benutzeraccounts teilen, sinkt der Administrationsaufwand ungemein. Außerdem erlaubt das Feature Programmierern, schnell mal eine Testinstanz aufzusetzen. Wer nicht als Hoster auftreten möchte und die Registierung neuer Blogs für User deaktiviert, möchte wahrscheinlich auch folgenden Eintrag in der wp-config.php vornehmen:

define( 'NOBLOGREDIRECT', '%siteurl%');

Er verhindert, dass beim Ansurfen unregistrierter Subdomains eine Meldung unterdrückt wird, dass die Registrierung deaktiviert sei, und leitet den Surfer stattdessen auf den Haupt-Blog weiter.

Veröffentlicht unter Software, Web-Anwendungen | Hinterlasse einen Kommentar

Great Place to Work in Münster*

So unterschiedlich mein Studium und Arbeit sind, umso ähnlicher ist die Arbeitsweise: Alles passiert am PC. In den selbstständigen Arbeitsphasen, also vor Klausuren und während der für die Bachelor-Thesis vorgesehenen Zeit, verbringt man mitunter einige Zeit am Schreibtisch, wohlmöglich große Teile des Tages im selben Raum. Das kann recht schnell eintönig werden und die eigene Effektivität sinkt langsam. Selbstständige kennen das Phänomen am besten.

Zum Glück bietet eine Stadt wie Münster viele andere Orte, an denen es sich Arbeiten und Lernen lässt. Die folgenden Tabelle fasst meine Erfahrungen aus der letzten Zeit zusammen. Grundvoraussetzung waren eine angenehme Athmosphäre, der freie Zugang möglichst lange am Tag, Internet-Zugang und der Genuss von Koffein in Getränkeform.

Universitäts- und Landesbibliothek (ULB)

CC BY-NC von flickr user plaetzchen
+ Stillarbeit oder netter Café-Bereich
+ Immer offen (8-24h)
+ Zugang zum Weltwissen vor Ort
- Nur Automatenverpflegung, kein Kaffee im Einzelarbeitsraum erlaubt!
- Netzzugang für Nicht-WWU-Studis ist schwierig
Café Gasolin

CC BY-NC-SA von flickr-User mimax
CC BY-NC-SA von flickr-User mimax

+ Gemütlich
+ Super Kaffee und günstig
+ Leckerer Kuchen
+ Tolle Musik
- Laute Musik
SpecOps

Copyright last.fm user regenjacke
Copyright last.fm user regenjacke

+ Super gemütlich
+ Wechselnde Ausstellungen mit junger Kunst
+ Kicker und Tischtennis für kreative Pausen
+ Club-Mate & Hermann-Brause
- Zeitfenster: Erst ab 2 auf, Abends Parties
Teilchen & Beschleuniger

Copyright teilchen & beschleuniger ug haftungsbeschränkt
Copyright teilchen & beschleuniger ug haftungsbeschränkt

+ Super super gemütlich
+ Leckerer Kaffee von Roestbar
+ Viele verschiedene Kaffeespezialitäten
+ Club-Mate & Fritz-Kola/-Limo
- Bagels haben ihren Preis

Und sonst? Natürlich gibt es auch noch andere Cafés mit kostenlosem WLan, wie z.B. die Filialen von Floyd’s und Starbucks. Am Kreativ-Kai bietet der Hot Jazz Club und ein T-Mobile HotSpot (Kostenfrei nur mit WLan-Flatrate, wie z.B. in den iPhone-Tarifen) Konnektivität. Interessant ist auch die Coworking Münster-Initiative, die zurzeit ein flexibles Büro in Münster startet. Zum Coden in netter Gesellschaft hat auch der Münsteraner Hackerspace warpzone immer einen Platz auf dem Sofa frei.

Natürlich hängt es von den persönlichen Bedürfnissen ab, wo man am produktivsten ist, vor allem von der Empfindlichkeit gegenüber ablenkenden Geräuschquellen. Mir und meiner Effektivität tut der Ortswechsel ab und zu gut. Für’s Arbeiten für meinen Arbeitgeber ist und bleibt das HomeOffice. Nur hier gibt’s den wirklich ergonomischen Schreibtisch, Bildschirm und die Möglichkeit ungestört zu telefonieren. Auch für die selbstständige Arbeit bleibt es der Dreh- und Angelpunkt, denn hier ist der Kaffee und die Club Mate noch am günstigsten ;-) .

(* Korrekterweise müsste es “Great Place for Working” heißen; dann wäre aber die Anspielung futsch.)

Veröffentlicht unter Real Life Stupidity, Studium | 2 Kommentare

Social Media Marketing mit Social Networks



Dieser Vortrag ist im Rahmen meines Seminars “IT-Marketing” entstanden. Ausnahmsweise geht’s also nicht ums Programmieren, ich hefte mir mal mit Absicht das “böse” Namensschild Social Media-Experte an. Ich möchte überblicksartig vorstellen, warum und wie Unternehmen Social Networks – insbesondere Facebook – als Marketing-Instrument nutzen können und sollten.

Download der Slides: Social Media Marketing mit Social Networks

Veröffentlicht unter Projekte | 2 Kommentare