IOException.de

Icon

Ausgewählter Nerdkram von Informatikstudenten der Uni Ulm

Mehrere Werte in Java-Methoden typsicher zurückgeben

Anders als manch andere imperative Programmiersprachen, unterstützt Java nur die Rückgabe eines Wertes bei einem Methodenaufruf. Jedoch ist es häufig interessant, mehrere Werte zurückzugeben. Grundsätzlich lassen sich hier zwei Szenarien unterscheiden. Bei der Rückgabe von mehreren gleichartigen Typen wird meist eine Klasse des Collections-Frameworks verwendet, wie zum Beispiel List oder ein Array. Manchmal will man aber auch völlig verschiedene Typen gemeinsam zurückgeben. Gängige Praxis ist es hier, ein Object-Array zurückzugeben und dann quasi beim Implementieren festzulegen, von welchem Typ die einzelnen Werte sind und entsprechen zurückzucasten. Dies ist leider weder typsicher, noch lässt sich die vorherige Festlegung im Code erzwingen. Abhilfe schafft hier eine generische Holder-Klasse, die einzelnen Werte typsicher kapselt und als einziger Rückgabewert verwendet werden kann.

Hier ein Beispiel für die Rückgabe über ein Object-Array:

private Object[] doItUnchecked()
{
	String s = "foo";
	Date d = new Date();

	return new Object[] { s, d };
}

Aufruf:

// unchecked variant: dangerous!
Object[] returnValues = t.doItUnchecked();
String s = (String) returnValues[0];
Date d = (Date) returnValues[1];

Eine generische Holderklasse (hier: immutable):

/**
 * Immutable holder type for two values.
 *
 * @author Benjamin Erb
 *
 * @param <F> type of first value
 * @param <S> type of second value
 */
public class PairHolder<F, S>
{
	private final F first;
	private final S second;

	public PairHolder(F first, S second)
	{
		this.first = first;
		this.second = second;
	}

	public F getFirst()
	{
		return first;
	}

	public S getSecond()
	{
		return second;
	}
}

Verwendung in Methode:

private PairHolder<String, Date> doItChecked()
{
	String s = "foo";
	Date d = new Date();

	return new PairHolder<String, Date>(s, d);
}

Aufruf:

// check variant: safe already at compile-time
PairHolder<String, Date> h = t.doItChecked();
String s = h.getFirst();
Date d = h.getSecond();

Die Holderklasse lässt sich auch noch beliebig erweitern, um Tripel, Quadrupel etc. zu halten. Wer für 2-Tupel keine eigene Klasse implementieren möchte, kann übrigens auf AbstractMap.SimpleEntry oder AbstractMap.SimpleImmutableEntry zurückgreifen.

Twitterbot in Perl

Perl war schon immer eine polarisierende Sprache. Die einen lieben sie, die anderen hassen sie. Die einen sind Fan der flexiblen Syntax, die anderen verfluchen die mangelnde Lesbarkeit. Sätze wie “Perl: Write once – never understand again” oder “Perl is the only language that looks the same before and after RSA encryption.” zielen genau hierauf ab.

Dennoch ist Perl eine beliebte Skriptsprache, insbesondere im Unix/Linux-Bereich (dank erkennbarer Verwandschaft zu Unix-Tools/Sprachen wie C, awk oder Shell-Builtins) zur Systemadministration oder allgemein zur schnellen Problemlösung. Aber auch im Web und in vielen speziellen Einsatzgebieten wie zum Beispiel der (DNA-)Sequenzanalyse ist Perl weiterhin eine bedeutende Sprache. Aufgrund ihrer Mächtigkeit gilt Perl mancherorts als “Swiss Army Chainsaw of Programming Languages”.
Natürlich sind mit Ruby, Python und diversen Java-Derivaten viele neue Skriptsprachen auf den Markt gekommen, und Perl 6 lässt (leider) weiterhin auf sich warten.

Trotzdem bin ich weiterhin ein großer Freund dieser Sprache. Allerdings muss ich zugeben, dass ich etwas voreingenommen bin – Perl war mit die erste “richtige” Programmiersprache, mit der ich in Kontakt kam (dann kam die damals weniger richtige Sprache PHP).

Die Vorlesung Skriptsprachen und Anwendungen bei den Mathematikern hat dafür gesorgt, mein Interesse für Perl wieder etwas zu beleben und ein kleines Projekt in Angriff zu nehmen. Als Resultat entstand ein kleiner Bot, der täglich den Mensaplan der Uni Ulm abgrast und die Ergebnisse bei Twitter veröffentlicht. So besteht nicht nur die Möglichkeit, durch das Folgen des Bots bei Twitter täglich über die Tageskarte informiert zu werden, sondern es entsteht quasi als “Abfallprodukt” ein bisher nicht existenter RSS-Feed.

Das kleine Projekt zeigt sehr schön, wie man mithilfe der mächtigen CPAN-Module in Perl alltägliche Aufgabe sehr effizient und straight forward lösen kann. Zum Parsen der HTML-Seite, die als Quelle benutzt wird, wird das Paket XML::LibXML benötigt. Hiermit lassen sich per XPath direkt die interessanten Inhalte extrahieren. Die leichtgewichtige Twitter-Library Net::Twitter::Lite sorgt zudem für eine einfach Twitter-Anbindung:

#!/usr/bin/perl
use strict;
use DateTime;
use Net::Twitter::Lite;
use XML::LibXML;

#Get date
my $today = DateTime->today();
die "No working day!\n" if($today->day_of_week()>5);

#Fetch url and load document as DOM tree
my $url = sprintf("http://www.uni-ulm.de/mensaplan/%04d-%02d-%02d.html",$today->year, $today->month,$today->day);
my $doc = XML::LibXML->new()->parse_html_file($url) or die "Error while fetching/parsing document!\n";

#Gather all list entries and extract mealtype and actual meal
my @meals = $doc->findnodes('//div[@class="meal"]');
my @tweets;
foreach (@meals)
{
	my ($mealtype, $meal) = ($_->find('./div[@class="mealtype"]'),$_->find('./div[@class="item"]'));
	$meal =	(length($meal)+length($mealtype) > 138 ? substr($meal,0,136-length($mealtype)).".." : $meal);
	push(@tweets, $mealtype.": ".$meal);
}
die "Error while fetching meals!\n" if(length(@tweets) == 0);

#Login to twitter and post entries in reverse order
my $nt = Net::Twitter::Lite->new(username => 'username', password => '...', clientname => "MensaBot",source => "web") or die "Error during twitter login procedure!\n";
$nt->update("="x 40);
foreach (reverse(@tweets))
{
	my $result = $nt->update($_);
}
$nt->update("Mensaplan Uni Ulm am ".$today->day.".".$today->month.".".$today->year.":   #uni #ulm #uulm #mensa #mensaplan");
exit;

Zugehöriger Crontab-Eintrag, wobei 1-5 für Werktage steht und 0 10 für 10:00 Uhr:

0 10 * * 1-5 /path/to/script.pl

Hiermit wird das Skript regelmäßig zu den gewünschten Zeiten ausgeführt.

Semantic Mashup

Aus meiner Seminararbeit zum Thema Semantic Mashups aus dem vergangenen Sommersemester ist nun ein kleiner Technical Report geworden. Im Paper werden Mashups – also Anwendungen, die Informationen verschiedener Webseiten vermischen – analysiert und verschiedene technische Grundlagen, die hierfür nötig sind erläutert. Desweiteren werden existierende Mashup-Engines und Architekturen vorgestellt, sowie Herausforderungen und Probleme beim Erstellen von Mashups aufgezeigt.
semantic_mashup_cloud
Abstract:

Nowadays, the World Wide Web has become the most important source of information for many people and is nearly indispensable. However, the information is spread on billions of web pages. So there is an increasing demand to combine the data of different web pages for an acquisition of information. Mashup applications assist the user at this task. This paper will give an overview about how to extract structured and semantical data out of web pages using different technologies and also shows, what types of mashup applications already exist. Furthermore we take a look at mashup architectures and engines and unresolved issues for mashup applications.

Benjamin Erb, Jan-Patrick Elsholz, Franz J. Hauck: Semantic Mashup: Mashing up Information in the Todays World Wide Web – An Overview. VS-R08-2009, 2009. [pdf] [bib]

SequentialMessageQueues in Java

Viele Netzwerkprotokolle teilen ihre Kommunikationsentitäten in Pakete oder Nachrichten auf. Manche Protokolle erwarten außerdem eine sequentielle Abarbeitung (z.B. TCP auf Transportebene), auch wenn die darunterliegenden Protokollschichten dass nicht unbedingt unterstützen. Für die Implementierung eines Nachrichtenpuffers für RTSP-Nachrichten, die ungeordnet ankommen können, aber sequentiell abgearbeitet werden müssen, habe ich eine entsprechende Datenstruktur in Java erstellt. RTSP-Nachrichten besitzen ein Cseq-Header-Feld, welches die einzelnen Nachrichten durchnummiert und als ordnendes Element genutzt werden kann.

Die folgende generische Implementierung erwartet, dass alle Nachrichtenelemete eindeutige und miteinander vergleichbare Identifier besitzen. Desweiteren erlaubt diese Implementierung zwar das parallele Schreiben in die Queue, allerdings sollte das Lesen durch einen einzelnen Thread realisiert werden. Ansonsten kann die Ordnung nach dem Entnehmen aus der Queue durch unterschiedlich lange Laufzeiten der Worker-Threads wieder verloren gehen. Außerdem realisiert diese Implementierung die sequentielle Ordnung eines vollständigen Nachrichtenstroms. Nachrichtenverluste oder Timeouts werden nicht behandelt. Hierfür eignen sich eher Automatic repeat request Protokolle.

Interface für MessageQueue
Eine MessageQueue bietet die grundlegenden Funktionen zum Einfügen und Entfernen von Elementen sowie Hilfsmethoden für die Größe der Queue an.

/**
 * Interface for message queues.
 *
 * @author Benjamin Erb
 *
 * @param <E>
 *            Element type
 */
public interface MessageQueue<E>
{
	/**
	 * Adds element to queue. Blocks until element can be added.
	 *
	 * @param e
	 *            new element
	 * @throws InterruptedException
	 */
	void push(E e) throws InterruptedException;

	/**
	 * Takes an element from the queue. Blocks until element becomes available.
	 *
	 * @return taken element
	 * @throws InterruptedException
	 */
	E pop() throws InterruptedException;

	/**
	 * Gets the size of the queue
	 *
	 * @return
	 */
	int size();

	/**
	 * Checks whether queue is empty or not.
	 *
	 * @return
	 */
	boolean empty();

}

Interface für speziellen Comparator
Dieses spezielel Comparator-Interface fügt Methoden hinzu für das Erfragen von vorherigen und nachfolgenden Identifiern an. Außerdem können Nachrichten, Identifier oder eine Kombination aus beidem verglichen werden.

import java.util.Comparator;

/**
 * An enhanced comparator interface for retrieving preceding and subsequent identifiers.
 *
 * @author Benjamin Erb
 *
 * @param <E> Element type
 * @param <T> Element identifier
 */
/**
 */
public interface SequentialComparator<E, T extends Comparable<T>> extends Comparator<E>
{
	/**
	 * Returns the subsequent identifier of a given entity.
	 *
	 * @param t
	 *            entity
	 * @return subsequent identifier
	 */
	T getNext(E e);

	/**
	 * Returns the preceding identifier of a given entity.
	 *
	 * @param t
	 *            entity
	 * @return preceding identifier
	 */
	T getPrevious(E e);

	/**
	 * Compares two entities.
	 *
	 * @param t1
	 *            entity 1
	 * @param t2
	 *            entity 2
	 * @return a negative integer, zero, or a positive integer as the first
	 *         argument is less than, equal to, or greater than the second.
	 */
	int compare(T t1, T t2);

	/**
	 * Compares an entity and an identifier.
	 *
	 * @param t1
	 *            entity
	 * @param e2
	 *            identifier
	 * @return a negative integer, zero, or a positive integer as the first
	 *         argument is less than, equal to, or greater than the second.
	 */
	int compare(T t1, E e2);

	/**
	 * Compares an identifier and an entity.
	 *
	 * @param e1
	 *            identifier
	 * @param t2
	 *            entity
	 * @return a negative integer, zero, or a positive integer as the first
	 *         argument is less than, equal to, or greater than the second.
	 */
	int compare(E e1, T t2);
}

SequentialMessageQueue Implementierung
Die eigentliche Queue-Implementierung greift intern auf eine PriorityBlockingQueue zurück, allerdings wird durch die Kapselung sichergestellt, dass nur das nächste zu erwartende Element entnommen werden kann.

import java.util.concurrent.PriorityBlockingQueue;

/**
 * A message queue for sequential message processing. This queue orders incoming
 * messages entities by their identifiers and outputs entites in-order. This
 * queue supports more than one writing thread. However, it is designed for one
 * reading/consuming thread in order to prevent out-of-order processing by
 * multiple threads.
 *
 * @author Benjamin Erb
 *
 * @param <E>
 *            Message entity
 * @param <T>
 *            Message identifier
 */
public class SequentialMessageQueue<E, T extends Comparable<T>> implements MessageQueue<E>
{
	/**
	 * Lock object for queueing
	 */
	private final Object lock = new Object();

	/**
	 * internal queue
	 */
	private final PriorityBlockingQueue<E> internalQueue;
	/**
	 * comparator
	 */
	private final SequentialComparator<E, T> comparator;

	/**
	 * Represents the identifier of the next expected entity
	 */
	private T expectedIdentifier;

	public SequentialMessageQueue(SequentialComparator<E, T> comparator, T initialIdentifier)
	{
		this.internalQueue = new PriorityBlockingQueue<E>(16, comparator);
		this.comparator = comparator;
		this.expectedIdentifier = initialIdentifier;
	}

	@Override
	public boolean empty()
	{
		return internalQueue.isEmpty();
	}

	@Override
	public E pop() throws InterruptedException
	{
		synchronized (lock)
		{
			E firstElement;
			while ((firstElement = internalQueue.peek()) == null || comparator.compare(firstElement, expectedIdentifier) != 0)
			{
				lock.wait();
			}
			internalQueue.remove();
			expectedIdentifier = comparator.getNext(firstElement);
			return firstElement;
		}
	}

	@Override
	public void push(E e) throws InterruptedException
	{
		synchronized (lock)
		{
			internalQueue.put(e);
			lock.notifyAll();
		}

	}

	@Override
	public int size()
	{
		return internalQueue.size();
	}

	/**
	 * Returns the used comparator
	 *
	 * @return
	 */
	protected SequentialComparator<E, T> getSequentialComparator()
	{
		return comparator;
	}

}

Schnelle Quellcode-Navigation in Eclipse

Bei der Entwicklung größerer Java-Projekte kann schnell die Übersicht verloren gehen. Zum Glück bietet Eclipse eine Vielzahl von Shortcuts und Funktionen, um sich auch noch bei einer Vielzahl von Klassen zurecht zu finden.

  • Strg + 3
    Öffnet den intelligenten Quick Access Dialog.
  • Strg + Shift + R
    Öffnet einen Schnelldialog zum Öffnen einer Ressource. Ist insbesondere hilfreich, um eine Datei mit bekanntem Dateinamen direkt zu öffnen, ohne im Package Explorer zu suchen.
  • Strg + Shift + T
    Öffnet einen Schnelldialog zum Öffnen einer Java-Ressource. In der Auswahl kann der Name der Klasse/Interface/etc. direkt eingegeben werden.
  • Strg + Linksklick auf Klassenname
    Sprung zum Quelltext der Klasse, auf die im Editor geklickt wird.
  • Strg + T
    Übersicht der Vererbungshierarchie der Klasse, die sich im Fokus des Editors befindet. Nochmaliges Drücken von Strg + T dreht die Hierarchierichtung (Superklassen/Subklassen) um.
  • Strg + O
    Übersicht der Membervariablen und Methoden der aktuellen Klasse. Nochmaliges Drücken von Strg + O zeigt zusätzlich geerbte Member an.
  • Strg + Shift + G
    Sucht nach Verwendungen der Methode im Fokus des Editors in alles Klassen der Workspaces.
  • Strg + . und Strg + '+'
    Sprung durch die Quelltextzeilen mit Warnungen
  • Strg + L
    Öffnet Dialog für einen Sprung in eine bestimmte Codezeile.
  • Strg + E
    Zeigt Liste aller offenen Editors-Tabs an und ermöglicht Direktauswahl eines offenen Editorstabs per Texteingabe.
  • Strg + Bild Auf und Strg + Bild Ab
    Springen durch die offenen Editor-Tabs.
  • Alt + ← und Alt + →
    Springen durch die Historie der geöffneten Tabs.

Die Geolocation API in Firefox 3.5

Seit Version 3.5 unterstützt der Webbrowser Mozilla Firefox die Geolocation API – eine API zur Unterstützung von location aware webservices, also Webseiten oder Dienste, die gezielt den Ort des Benutzers mit einbeziehen und sich entsprechend anpassen. Die implementierte Geolocation API basiert auf einem Draft des W3C.
Die Geolocation API ist in das Javscript-Browsermodell integriert worden und bietet nun geolocation als Kindobjekt von navigator an. Unterstütz der Browser die API nicht oder hat sie deaktiviert, so ist navigator.geolocation nicht verfügbar. Dies sollte aus Kompatibilitätsgründen immer als erstes getestet werden.
Ist das Objekt verfügbar, so kann mit getCurrentPosition() eine Abfrage der Koordinaten abgesetzt werden, die asynchron läuft. Als Parameter erwartet diese Methode eine Callback-Methode für die Verarbeitung des Ergebnisses und optional eine zweite Methode zur Fehlerbehandlung.
Eine Live-Demo mit einer Visualisierung mit OpenStreetMap findet man unter anderem auf 3liz.org/geolocation.

if (navigator.geolocation)
{
	navigator.geolocation.getCurrentPosition(function(position)
	{
		alert('Position:' + position.coords.latitude + ' / ' + position.coords.longitude);
	});
}
else
{
	alert("Geolocation API nicht verfügbar.");
}

Doch wie funktioniert diese Lokalisierung? Firefox nutzt hierfür die Google Location Services. Dieser Dienst versucht eine öffentliche IP anhand von verschiedenen Informationen zu einer ungefähren geografischen Position zu mappen, was häufig sehr ungenau ist. Ist jedoch WLan verfügbar, so benutzt dieser Dienst eine andere Strategie. Es wird eine Liste aller erreichbaren Access Points, deren MAC-Adresse sowie deren Signalstärke übermittelt. Diese Daten werden mit einer großen Datenbank abgeglichen und eine ungefähre Position trianguliert. Hierfür müssen zunächst die entsprechenden Daten in einer Datenbank gesammelt worden sein – man muss Straße für Straße mit allen erreichbaren WLan Access Points kartografieren. Bei unseren Tests stellte sich heraus, dass dies in Ulm und Neu-Ulm bereits passiert ist, die Ergebnisse waren durchweg gut und oft auf etwa 10 Meter genau!
Interessant wäre ein Blick in das Innere dieses Dienstes, ob er zum Beispiel selbstlernend ist und mit der Zeit neue Access Points anhand der übermittelten Datensätze einer genauen Position zuordnen und hinzufügen kann. Aber auch aus datenschutzrechtlichen Sicht sind Details solcher Dienste sehr interessant.

Statische Code-Analyse für Java mit FindBugs

findbugs1FindBugs ist ein Open-Source Tool zur statischen Quellcode-Analyse für Java. Es sucht in Java-Code nach typischen Fehlermustern – hierbei wird lediglich der Java Bytecode betrachtet, der Code wird nicht ausgeführt. Hierfür besitzt FindBugs eine reichhaltige Sammlung von typischen Bugs. Diese basieren hauptsächlich auf schwierigen Sprachfeatures (z.B. fehleranfälliger Umgang mit intrinsischen Condition Queueswait/notify/notifyAll), häufig missverstandenen API Funktionen (z.B. Start eines Threads durch Aufruf der run()-Methode anstatt start() ) und markanten Fehlern wie Typos, falschen Vergleichsoperationen (Stringvergleiche mit == anstatt equals) etc. Auch Korrektheit und Korrektheit bei nebenläufigen Programmen sowie Performance- und Sicherheitsaspekte werden beachtet. Eine komplette Liste aller bekannter Fehlermuster gibt es auf der FindBugs Bug Descriptions Seite.

Ein solches Tool kann nie sorgfältiges Design & Implementierung, noch ausgebieges Testen und Debuggen ersetzen, jedoch ist es als weiteres Werkzeug bei der Suche nach Fehlern insbesondere in größeren Projekten sehr hilfreich. Neben einer Kommandozeilenvariante und einer GUI existiert außerdem ein Eclipse-Plugin, womit sich FindBugs vollständig in Eclipse integrieren lässt. Über den Package Explorer lassen sich Analyseprozesse starten, gefunden Fehlermuster werden sowohl in einem Bux Explorer als auch inline im Editor angezeigt.

Java VisualVM

jvisualvm1Seit Version 6 Update 7 besitzt das Java Development Kit ein weiteres hilfreiches Entwicklungstool, nämlich VisualVM. Die Anwendung ermöglicht das Überwachen und Profiling laufender Java-Anwendungen (auch entfernter) virtueller Maschinen. Neben Merkmalen wie dem aktuellen Verbrauch an Speicher, der Größe des Heaps, Anzahl von Threads und geladener Klassen laufender Prozesse lassen sich zusätzlich aus einem erzeugbaren Heapdump zur Laufzeit Informationen über instanziierte Objekte erfragen, wie es vom Eclipse-Debugger bekannt ist. Auch die Garbage Collection kann hier manuell ausgelöst werden. Threads werden inklusive ihrer Zustände chronologisch visualisiert. Dies ist insbesondere beim Debugging von Anwendungen interessant, die intensiv Gebrauch von Multithreading machen. Durch die Anzeige der Zustände der Threads werden Monitore (Locks) sichtbar gemacht. Außerdem können über einen Threadump die einzelnen Callstacks der Threads inspiziert werden.

jvisualvm2Im CPU-Profiling können die Anwendungen in Echtzeit daraufhin untersucht werden, welche Methoden wie oft aufgerufen werden und wieviel CPU-Zeit sie benötigen, was bei der Suche nach möglichen Optimierungsansätzen hilfreich sein könnte. Das Memory-Profiling zeigt die Anzahl von Instanzen, den Speicherverbrauch, sowie den prozentualen Anteil am gesamten Speicherplatz von Klassen und primitiven Datentypen an sowie Informationen zur Garbage Collection.

Durch Plugins lässt sich das Programm noch um weitere Funktionen ergänzen. Entstanden ist das Projekt aus der Sun-eigenen NetBeans-IDE und basiert auch heute noch auf dessen NetBeans-RCP Framework. Zu finden ist es bei jeder JDK Installation ab 6u7 im Ordner bin/jvisualvm. Es lässt sich für ältere JDK-Versionen über einen Download von der Projektseite separat installieren .

Originalartikel: Java VisualVM

Rekonstruktion von Binärbäumen anhand von Baumtraversierungen

Anscheinend war es wohl mal wieder Zeit für einen etwas theoretischeren Beitrag. Binärbäume sind in der Informatik eine wichtige Datenstruktur, mit der sich beispielsweise Rechenterme abspeichern lassen. Sie bestehen aus Knoten, die einen linken und/oder rechten Knoten besitzen können, welche selbst wieder Unterknoten besitzen können. Mehr dazu findet man unter anderem bei Wikipedia.

Binärbäume werden über rekursive Aufrufe traversiert, bei (Binär-)Bäumen gibt es hauptsächlich drei wichtige Traversierungen: Pre-Order, In-Order und Post-Order. Ein Traversierungschritt besteht jeweils aus drei Teilschritten: Auswertung des aktuellen Knotenwerts, und der rekursive Abstieg in den linken und rechten Unterknoten. Der Name gibt jeweils an, an welcher Stelle die Auswertung des aktuellen Knotens stattfindet. Bei einer Post-Order-Traversierung wird also erst, der linke und der rechte Knoten rekursiv aufgerufen, und dann erst der aktuelle Knoten selbst ausgewertet. Hier ein Beispiel:

Pre-Order: L A H L O
In-Order: H A L L O
Post-Order: H L A O L
Nun ist es eine beliebte (Prüfungs-)Aufgabe, anhand zweier gegebenen Traversierungen den Originalbaum rekonstruieren zu lassen. In manchen Lehrbüchern ist zu finden, dass dies mit zwei Traversierungen möglich ist. Allerdings misslang mir dies bei einigen Versuchen mit Pre- und Post-Order-Ausagabe und ich sah mir das Ganze genauer an. Die Aussagen ist nämlich nicht ganz korrekt, ohne eine In-Order-Ausgabe ist dies nur in bestimmten Situationen möglich (nämlich wenn der Baum vollständig ist). Doch wieso klappt es nur mit Pre & Post nicht? Hier ein Gegenbeispiel:

Bei beiden Bäumen ergibt sich als Pre-Order-Durchlauf „A B C“ und als Post-Order „C B A“, obwohl die Binärbäume nicht identisch sind.

Nun ein vollständiger Baum:

Hier ergeben sich folgende Traversierungen:
Pre-Order: A B D E C F G
Post-Order: D E B F G C A
Hiermit lässt sich der Baum rekursiv rekonstruieren, indem man die Traversierung rückwärts durchspielt und dabei jeweils Teilbäume wiederherstellt.
Wird nun jedoch der rote F-Knoten entfernt (was die Vollständigkeit aufhebt), so ist nur anhand des Pre- und Post-Order-Durchlaufs nicht mehr eindeutig, ob der Knoten G links oder rechts unterhalb des Knotens C sich befindet. Also lassen sich nur vollständige Bäume mit einer Kombination von Pre und Post rekonstruieren.

Bei allen anderen Bäumen ist dies mit einer Kombination eines In-Order-Druchlaufs zusammen mit einem Pre- oder Post-Order-Durchlaufs möglich.

Update: Nach längerer Suche bin ich im Internet noch auf diese Seite gestoßen, die das Problem ebenfalls anspricht und Rekonstruktionen noch genauer untersucht.

Mit Working Sets Eclipse aufräumen

Working Sets im Package ExplorerJedem Eclipse-Benutzer dürfte es bekannt vorkommen, wenn langsam die ganzen Projekte den Package Explorer füllen und dabei die Übersicht verloren geht. Natürlich besteht hier die Möglichkeit, durch verschiedene Workspaces die einzelnen Projekte oder Projektgruppen zu separieren, jedoch stellt eine Unterteilung in Workspaces eine sehr restriktive Trennung dar.
Abhilfe schaffen in Eclipse die so genannten Working Sets – wie bei allen Eclipse-Funktionen muss man halt erstmal überhaupt davon wissen. Working Sets lassen sich über New => Java => Java Working Set erstellen und erzeugen Überordner, in denen sich Projekte gruppieren lassen. Um im Package Explorer die Ansicht nach Working Sets aufzuschlüsseln, müssen diese jedoch als Top Level Elements gewählt werden.

Originalartikel: Mit Working Sets Eclipse aufräumen

ioexception.de

Benjamin Erb [] studiert seit 2006 Medieninformatik und interessiert sich insbesondere für Java, Web-Technologien, Ubiquitous Computing, Cloud Computing, verteilte Systeme und Informationsdesign.


Raimar Wagner studiert seit 2005 Informatik mit Anwendungsfach Medizin und interessiert sich für C++ stl, boost & Qt Programmierung, Scientific Visualization, Computer Vision und parallele Rechenkonzepte.


David Langer studiert seit 2006 Medieninformatik und interessiert sich für Web-Entwicklung, jQuery, Business Process Management und Java.


Sebastian Schimmel studiert seit 2006 Informatik mit Anwendungsfach Medizin und interessiert sich für hardwarenahe Aspekte, Robotik, webOs, C/C++ und UNIX/Linux.


Timo Müller studiert seit 2006 Medieninformatik. Er interessiert sich allen voran für Mobile and Ubiquitous Computing, systemnahe Enwticklung und verteilte Systeme, sowie Computer Vision.


Achim Strauß studiert seit 2006 Medieninformatik. Seine Interessen liegen in Themen der Mensch-Computer Interaktion sowie Webentwicklung und UNIX/Linux.


Tobias Schlecht studiert seit 2006 Medieninformatik und interessiert sich vor allem für Software Engineering, Model Driven Architecture, Requirements Engineering, Usability Engineering, Web-Technologien, UML2 und Java.


Fabian Groh studiert seit 2006 Medieninformatik. Seine Interessengebiete sind Computer Graphics, Computer Vision, Computational Photography sowie Ubiquitos Computing.


Matthias Matousek studiert seit 2007 Medieninformatik und interessiert sich besonders für Skriptsprachen, Echtzeitsysteme und Kommunikation.


Michael Müller [] studiert seit 2009 Medieninformatik. Er interessiert sich vor allem für Web-Technologien, Ubiquitous Computing, User-Interfaces, UNIX und Creative Coding.


Falco Nogatz [] studiert seit 2010 Informatik mit Anwendungsfach Mathematik. Er interessiert sich für Web-Technologien, Programmierparadigmen und theoretische Grundlagen.

Archiv

Mai 2012
M D M D F S S
« Apr    
 123456
78910111213
14151617181920
21222324252627
28293031