Logarithmische Achsen in R-Plots formatieren

Im Gegensatz zu gnuplot, werden in R-Plots die logarithmische Achsen nicht sehr schön formatiert. Das Paket SFSmisc schafft hier Abhilfe. In diesem Artikel beschreibe ich Schritt für Schritt, wie man ansehnliche logarithmische Achsen für R-Plots erstellt.

  1. Als Beispiel sollen Daten geplottet werden, die in einem doppelt logarithmischen Plot eine Gerade ergeben:
    x = 1:1000
    y = x^-1.5
  2. Nun werden diese Daten mit dem Befehl plot() in einem Koordinatensystem mit logarithmischer X- und Y-Achse (log="xy") dargestellt:
    plot(x, y, log="xy")

    Dabei kann man erkennen, dass es keine kleinen Striche zur Unterteilung der Bereiche zwischen den einzelnen Größenordnungen gibt:

    Plot mit logarithmischen Achsen. Standardmäßig werden keine Striche zwischen den Größenordnungen eingezeichnet.
    Plot mit logarithmischen Achsen. Standardmäßig werden keine Striche zwischen den Größenordnungen eingezeichnet.
  3. Es ist aber durchaus üblich, den Bereich zwischen zwei Größenordnungen mit 8 kleinen Strichen zu unterteilen. Diese Striche zeigen an, an welchen Stellen 20%, 30%, 40%, 50%, 60%, 70%, 80% oder 90% der folgenden Größenordnung erreicht wurden. Um das in R zu bewerkstelligen, muss zunächst das Paket SFSmisc installiert werden (siehe dazu auch: Funktion aus einem bestimmten R-Paket laden):
    # Installation
    install.packages("sfsmisc", dependencies=T)
    # Paket laden
    library(package = "sfsmisc")
  4. Im Anschluss plotten wir die Daten erneut, aber ohne dabei die Achsen zu beschriften (xaxt="n", yaxt="n"). Die Beschriftung der Achsen wird im Anschluss mit Hilfe des Befehls eaxis() aus dem Paket SFSmisc hinzugefügt:
    plot(x, y, log="xy", xaxt="n", yaxt="n")
    sfsmisc::eaxis(side=1)   # X-Achse
    sfsmisc::eaxis(side=2)   # Y-Achse

    Im neuen Plot sind nun auf jedenfall acht Striche zur Unterteilung einer Größenordnung zu sehen:

    Erstellt man die Achsen eines Plots mit Hilfe des Befehls eaxis() aus dem Paket SFSmisc, so wird der Bereich zwischen zwei Größenordnungen in neun Teile unterteilt. Eventuell werden aber nicht nur die Zahlen für die Größenordnungen eingetragen, sondern auch für dazwischen liegende Werte (hier z.B. 5, 50 und 500).
    Erstellt man die Achsen eines Plots mit Hilfe des Befehls eaxis() aus dem Paket SFSmisc, so wird der Bereich zwischen zwei Größenordnungen in neun Teile unterteilt. Eventuell werden aber nicht nur die Zahlen für die Größenordnungen eingetragen, sondern auch für dazwischen liegende Werte (hier z.B. 5, 50 und 500).

    In diesem Beispiel wurde nicht explizit angegeben, welche Zahlen auf den Achsen zu sehen sein sollen. Daher sind nicht nur die Größenordnungen, sondern auch Werte dazwischen, als Zahlen eingetragen.

  5. Daher kann man nun noch explizit angeben, welche Zahlen sichtbar sein sollen (at=)
    plot(x, y, log="xy", xaxt="n", yaxt="n")
    sfsmisc::eaxis(side=1, at=10^c(0:3))
    sfsmisc::eaxis(side=2, at=10^c(-4,-2,0))

    In diesem Plot wurden nur Zahlen für die Größenordnungen angegeben. Auf der X-Achse wurde jede, auf der Y-Achse nur jede zweite Größenordnung mit einer Zahl versehen.
    In diesem Plot wurden nur Zahlen für die Größenordnungen angegeben. Auf der X-Achse wurde jede, auf der Y-Achse nur jede zweite Größenordnung mit einer Zahl versehen.

Mathematische Gleichung nach einer bestimmten Variablen auflösen lassen

Manchmal möchte man eine mathematische Gleichung umstellen, bzw. nach einer der Variablen auflösen. Je nachdem wie kompliziert die Gleichung ist, oder wie lange man so etwas nicht mehr gemacht hat, kann das ganz schon lästig sein. Numerik-Software wie Mathematica können einem die Arbeit deutlich erleichtern. Einige der Mathematica-Funktionen stehen auch online auf www.WolframAlpha.com (Wikipedia) zur Verfügung. In diesem Artikel beschriebe ich, wie man eine einfache Formel nach einer einer Variablen auflösen lassen kann.

  1. Nehmen wir an, wir haben folgende Gleichung:
    a = b + x
  2. Diese Formel wollen wir nach x auflösen. Das Ergebnis ist hoffetlich jedem klar: Auf beiden Seiten -b, ergibt:
    a - b = x

    bzw.

    x = a - b
  3. In Mathematica könnte man diese Aufgabe mit der Funktion Solve lösen (siehe auch: „equation solving„).
    Solve[a==b+x, x]
  4. Gibt man diesen Befehl auf WolframAlpha ein, erhält man das gesuchte Ergebnis:
    Die auf WolframAlpha angezeigte Lösung für das Problem "Löse die Gleichung a = b + x nach x auf"
    Die auf WolframAlpha angezeigte Lösung für das Problem „Löse die Gleichung a = b + x nach x auf“
  5. Da es sich bei WolframAlpha um eine semantische Suchmaschine handelt, kann man auch ähnliche Sachen eingeben, wie z.B.:
    solution of a=b+x for x

Apple Befehlstaste (⌘) in Blog-Artikeln verwenden

Gelegentlich muss ich an einem Apple-Gerät (meist einem iMac) arbeiten. Über meine Erfahrungen berichte ich unter anderem in diesem Blog. Daher komme ich nicht drumherum, die Befehlstaste (; Command key) in den ein oder anderen Beitrag einzufügen.

Dafür gibt es zwei Möglichkeiten:

  • Zum einen kann man das ⌘-Zeichen direkt in den Quelltext (oder das Editor-Fenster) kopieren. Das funktioniert bei mir, da ich in der Regel den UTF-8 Zeichensatz für meine Blogs und Internetseiten verwende.
  • Falls man nicht den UTF8-Zeichensaz verwendet, kann man auch den Unicode-Befehl (⌘) in seinen Quelltext einbauen:
    1
    
    Das ⌘-Zeichen über den HTML-Befehl ⌘ einfügen.

    Das ergibt:

    Das ⌘-Zeichen über den HTML-Befehl ⌘ einfügen.

Hinweis: Einige Browser können das Zeichen nicht darstellen (z.B. der Standard-Browser auf meinem Android-Tablet).

Die Version installierter Pakete im Terminal herausfinden

Kürzlich sollte ich einem Administrator die Version der VMware-Tools mitteilen, die auf meiner virtuellen Maschine installiert waren. Allerdings war (und ist) mir kein Befehl bekannt, mit dem ich diese Informationen direkt von Programmen des Paketes erhalten kann. Es ist aber möglich, die Version des installierten Paketes über den Debian Paketmanager (dpkg) zu ermitteln (UbuntuUsers-Forum).

Dazu lässt man sich zunächst (mit Hilfe von dpkg) eine Liste von Kurzbeschreibungen aller installierten Pakete ausgeben. Mit Hilfe von grep lässt man allerdings nur diejenigen Zeilen anzeigen, in denen der Namen des Paketes vorkommt (in meinem Falle open-vm-tools):

dpkg -l | grep open-vm-tools

In der Ausgabe kann man dann die Version ablesen:

ii  open-vm-tools  2012.05.21-724730-0ubuntu2  i386  tools and components for VMware guest systems (CLI tools)

In meinem Falle konnte der Administrator die virtuelle Maschine problemlos über den vSphere-client neu starten.

Ubuntu-Version im Terminal herausfinden

Wer ganz schnell die Version seiner Linux-Distrbution herausfinden möchte, kann dazu den Befehl lsb_release verwenden (siehe auch Ubuntu-Hilfe und UbuntuUsers-Forum). Durch diesen Befehl erhält man Informationen über allgemeine Linux Schnittstellen (Linux Standard Base; LSB), sowie Distributions-spezifische Informationen.

  • Nach der Eingabe von:
    lsb_release -a

    erhält man z.B.:

    No LSB modules are available.
    Distributor ID:	Ubuntu
    Description:	Ubuntu 12.10
    Release:	12.10
    Codename:	quantal
  • Weitere Informationen über mögliche Parameter erhält man in den Manpages (Online Manpage zu lsb_release):

    man lsb_release
  • Eine andere (weniger umfangreiche Methode) habe ich auf aphilia.info gefunden:
    cat /etc/issue

    Mit dem Resultat:

    Ubuntu 12.10 \n \l
    

Meine TeXstudio-Makros

TeXstudio wurde erstellt, um die Arbeit mit LaTeX zu vereinfachen. Eine Möglichkeit ist die Verwendung sogenannter Makros (oder Macros). Mit der Hilfe von Markos kann man umfangreiche Anweisungen ausführen lassen oder LaTeX-Anweisungen in den Quelltext einfügen. In diesem Artikel liste ich solche Markos auf, die ich derzeit verwende. Weitere Möglichkeiten von Makros werden im Handbuch von TeXstudio beschrieben.

Makros können in TeXstudio unter Makros / Makros bearbeiten verwaltet werden. Ich benutze Makros vor allem um LaTeX-Anweisungen direkt beim Tippen in meinen Quelltext einfügen zu lassen. Dazu dienen Auslöseimpulse (Trigger) und deren Abkürzungen (Abbreviations). Legt man z.B. ein Makro mit dem Trigger BILD an, so wird nach der Eingabe von BILD dieser Text durch den definierten LaTeX-Text ersetzt.

Beispiel für die ein benutzerdefiniertes Makro in TeXstudio. Nach dem speichern des Markos werden die Zeichenketten \bild und BILD beim Tippen automatisch durch den angegebenen LaTeX-Text ersetzt.
Beispiel für die ein benutzerdefiniertes Makro in TeXstudio. Nach dem speichern des Markos werden die Zeichenketten \bild und BILD beim Tippen automatisch durch den angegebenen LaTeX-Text ersetzt.

Makro: Bild einfügen

Nach der Eingabe von \bild oder BILD, werden diese Zeichenketten durch LaTeX-Befehle zum Einbinden eines Bildes ersetzt. Damit die unten stehenden Befehle funktionieren, muss in der Präambel das Paket graphicx eingebunden werden (z.B. \usepackage[pdftex]{graphicx}).

Name: Bild einfügen
Trigger: BILD
Abbreviation: \bild
LaTeX-Text:
\begin{figure}
\includegraphics[width=\textwidth]{Bilder/todo.jpg}
\caption{\textbf{XXX.}
XXX.
}
\label{Fig:XXX}
\end{figure}

Makro: Tabelle einfügen

Nach der Eingabe von \tabelle oder TABELLE, werden diese Zeichenketten durch LaTeX-Befehle für eine Tabelle ersetzt. Damit die unten stehenden Befehle funktionieren, müssen in der Präambel zwei Pakete eingebunden werden:

  • \usepackage{tabularx} – Tabelle, die automatisch an die Breite der Seite angepasst werden kann (über ein X bei der Angabe der Ausrichtung innerhalb der Tabelle).
  • \usepackage{booktabs} – Für die Befehle \toprule, \midrule und \bottomrule.
Name: Tabelle einfügen
Trigger: TABELLE
Abbreviation: \tabelle
LaTeX-Text:
\begin{table}
\caption{TabellenTitel}
\label{Tab:Parameter}
\begin{tabularx}{\textwidth}{ llX }
	\toprule
	Parameter & Typical value & Meaning\\
	\midrule
	$XXX$ & $XXX$ & XXX.\\
	$XXX$ & $XXX$ & XXX.\\
	\bottomrule
\end{tabularx}
\end{table}

Weitere Informationen zu Triggern

Trigger werden als Reguläre Ausdrücke interpretiert. Daher können sie deutlich mehr, als nur eine zu ersetzende Zeichenkette definieren:

Wenn dieser Triggertext in einem tex-Dokument geschrieben wird, so wird durch das aktuelle Makro ersetzt.

Wenn der Trigger mit (?<=etwas) anfängt, so passiert dies nur wenn "etwas" vor den restlichen Teil des Triggers geschriben wurde. Da der Triggertext kein einfacher Suchtext, sondern eine regulärer Suchausdruck ist, kann (?<=\S) verwendet werden, um Ersetzungen nach einem Wort und (?<=\s|^) um Ersetzungen vor einem Wort auszulösen. Man kann den speziellen Wert ?txs-start verwenden, um das Skript bei txs start zu starten.

Eine große Datei in viele kleine Dateien zerlegen

Ich hatte gerade eine sehr große Datei (3.3GB), die ich über eine langsame Internetverbindung auf einen Server verschieben wollte. Der Vorgang würde mehrere Stunden dauern. Die Wahrscheinlichkeit, dass der Upload unterbrochen würde, wäre relativ groß. In dem Falle müßte ich nochmal von vorne beginnen. Daher habe ich die Dateien in einzelne Dateien zerlegt. In diesem Artikel erkläre ich, wie man eine große Datei aufteilt und im Anschluss wieder zusammenfügt.

Ich habe eine Datei ergebnisse.zip, die ich in 10 MB große Stücke zerteilen möchte.

  1. Um den Erfolg überprüfen zu können, ermittle ich zunächst eine Prüfsumme (Hier: MD5-String) der Ausgangsdatei:
    md5sum ergebnisse.zip > ergebnisse.zip.md5
  2. Mit Hilfe des Programms split teile ich die Datei in 10MB große Stücke:
    split -b 10M ergebnisse.zip ergebnisse_split.zip.

    Dadurch werden viele Dateien erzeugt, die folgenden Aufbau haben:

    ergebnisse_split.zip.aa
    ergebnisse_split.zip.ab
    ergebnisse_split.zip.ac
    ergebnisse_split.zip.ad
    ...
    ergebnisse_split.zip.zy
    ergebnisse_split.zip.zz
    
  3. Nun kann man diese Dateien z.B. per SSH auf einem Server laden:
    scp ergebnisse_split.zip.* user@server.domain:~/zielordner

    Sollte nun der Vorgang unterbrochen werden, kann man im Anschluss einfach bei der Datei beginnen, bei der der Upload unterbrochen wurde.

  4. Nach erfolgtem Upload fügt man die Dateien mit Hilfe von cat einfach wieder zusammen:
    cat ergebnisse_split.zip.* > ergebnisse_cat.zip
  5. Nun muss nur noch geprüft werden, ob die zusammengefügte Datei den gleichen Inhalt wie die Ausgangsdatei hat. Dazu berechnet man erstmal die MD5-Summe:
    md5sum ergebnisse_cat.zip > ergebnisse_cat.zip.md5

    Wenn alles geklappt hat, stehen in ergebnisse.zip.md5 und ergebnisse_cat.zip.md5 die gleichen MD5-Summen.

  6. Weitere Möglichkeiten findest Du im Wiki von UbuntuUsers.

Mathematische Formeln in Glossar-Einträgen verwenden

Ein Glossar hilft dem Leser, auf schnellem Wege eine kurze Erkläung für verwendete Fachbegriffe zu finden. In LaTeX ist es möglich, automatisch ein Glossar erzeugen zu lassen. Dazu erstellt man in der Präambel mit dem Befehl \newglossaryentry{LABEL}{} einen neuen Eintrag, und bindet ihn dann mit dem Befehl \gls{LABEL}, \Gls{LABEL}, \plspl{LABEL} oder \Glspl{LABEL} in den Text ein. Verwendet man allerdings mathematische Formeln im Namen des Glossar-Eintrags, so wird diese Formel in der Überschrift im Glossar nicht fett geschrieben. In diesem Artikel beschreibe ich, wie man Glossar-Einträge mit mathematischen Formeln korrekt formatieren kann.

Zunächst muss in der Präambel das Paket glossaries eingebunden werden.

% Glossaries-Paket sollte nach dem hyperref-Paket geladen werden.
% \usepackage[nonumberlist,acronym,toc,section]{glossaries}
\usepackage[toc]{glossaries}
\makeglossaries

Das Problem

Im Anschluss kann man einen Glossar-Eintrag hinzufügen (Hier z.B. zum Fixations-Index (Fst) aus der F-Statistik):

\newglossaryentry{Fst}{
  name        = {$F_{st}$-Wert},
  description = {Fixations-Index,...},
  sort        = {fst-wert}
}

Nun kann man den Eintrag im Text einbinden:

Ein Text, der den Begriff \gls{Fst} enthält.

Im Text selbst wird der Eintrag korrekt angezeigt:

Link zum Glossar-Eintrag, der in normaler Schriftgröße in den Text eingefügt wurde.
Link zum Glossar-Eintrag, der in normaler Schriftgröße in den Text eingefügt wurde.

In Glossar ist die Formel allerdings nicht Fett geschrieben:

Standardmäßig werden mathematische Formeln in den Überschriften der Glossareinträge nicht fett geschrieben.
Standardmäßig werden mathematische Formeln in den Überschriften der Glossareinträge nicht fett geschrieben.

Ein erster Lösungsversuch

Um nun auch die Formel fett zu schreiben, kann man den Befehl \bm aus dem gleichnamigen Paket (bm) verwenden (siehe auch Stackoverflow):

\usepackage{bm}
 
\newglossaryentry{Fst}{
  name        = {$\bm{F_{st}}$-Wert},
  description = {Fixations-Index,...},
  sort        = {fst-wert}
}

Nun wird auch der Begriff Fst aus der Mathe-Umgebung in der Überschrift des Glossar-Eintrags fett geschrieben:

In der Glossar-Überschrift wird mit Hilfe des Befehls \bm die Formel fett geschrieben.
In der Glossar-Überschrift wird mit Hilfe des Befehls \bm die Formel fett geschrieben.

Allerdings wird Fst nun auch innerhalb des laufenden Textes fett geschrieben:

Unter Umständen wird nach der Formatierung der Formel, die Formel auch im Text fett geschrieben.
Unter Umständen wird nach der Formatierung der Formel, die Formel auch im Text fett geschrieben.

Die Lösung

Nun soll die Formel nur in der Glossar-Überschrift, aber nicht im Text fett geschreiben werden. Dazu fügt man zusätzlich den text-key hinzu, ohne diesen mit \bm zu formatieren (siehe Stackoverflow):

\newglossaryentry{Fst}{
  text        = {$F_{st}$-Wert},
  name        = {$\bm{F_{st}}$-Wert},
  description = {Fixations-Index,...},
  sort        = {fst-wert}
}

Schlussbemerkungen

  • Wenn die Formel am Anfang steht, funktionieren die Befehle für die Großschreibung nicht mehr. \gls und \glspl können problemlos verwendet werden. Verwendet man allerdings \Gls oder \Glspl bekommt man folgende Fehlermeldung:

    ! Extra }, or forgotten $.

  • Wenn man Formeln im Namen des Glossar-Eintrags verwendet, muss man auf jedenfall darauf achten, dass ein Wert für die Sortierung angegeben ist. Das geht mit Hilfe des sort-Schlüssels.

Kleinsten und größten Wert einer ArrayList ermitteln

Manche Zahlen und Objekte speichere ich in einer ArrayList. Hier kann man relativ leicht Objekte hinzufügen (.add()) oder entfernen (.remove()). In diesem Artikel beschreibe ich, wie man den größten und den kleinsten Wert (Minumum und Maximum) einer ArrayList bestimmt.

Für eine ArrayList<Integer>

Am einfachsten ist die Bestimmung des Minimums und des Maximums bei einer Liste von Objekten mit einer natürlichen Reihenfolge, wie z.B. Integer-Zahlen. In dem Falle kann man die statischen Methoden max() und min() der Collections-Klasse verwenden. Je nachdem wie die Liste aufgebaut ist, kann es allerdings auch effizientere Wege geben (siehe Stackoverflow und Zparacha-Blog).

ArrayList<Integer> liste = new ArrayList<Integer>();
liste.add(100);
liste.add(200);
liste.add(110);
liste.add(99);
 
System.out.println("Maximum: " + Collections.max(liste));
System.out.println("Minimum: " + Collections.min(liste));

Vollständiges Beispiel:

package de.fenon.test;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
 
/**
 * Beispiel: Kleinsten und größten Wert in einer ArrayList finden.
 * @author fenon.de
 */
public final class HauptProgramm {
  /** Zahl der Messungen. */
  static final Integer STICHPROBE = 10;
  /** Maximalwert. */
  static final Integer MAXIMUM = 10;
  /** Seed des Zufallszahlen-Generators. */
  static final Integer SEED = 1234567891;
 
  /**
   * Privater Konstruktor.
   * Dadurch kann kein Objekt der Klasse "Hauptprogramm" erzeugt werden.
   */
  private HauptProgramm() {}
 
  /**
   * main()-Methode.
   * @param args - Parameter der Kommandozeile.
   */
  public static void main(final String[] args) {
    ArrayList<Integer> liste = new ArrayList<Integer>();
    // Erzeuge zufällige Messwerte
    Random generator = new Random(SEED);
    for (int i = 0; i < STICHPROBE; i++) {
      liste.add(generator.nextInt(MAXIMUM));
    }
    // Gib die Messwerte aus
    for (Integer element:liste) {
      System.out.println(element);
    }
    // Gib Kleinsten und Größten Wert aus
    System.out.println("Maximum: " + Collections.max(liste));
    System.out.println("Minimum: " + Collections.min(liste));
 
  } // ENDE: main()
 
} // ENDE: HauptProgramm

Für eine ArrayList mit komplexeren Objekten

Man kann allerdings auch den minimalen und maximalen Wert eigener/komplexerer Objekte bestimmen. Im folgenden Beispiel habe ich eine Liste von Objekten des eigenen Typs Website. Mit Hilfe eines Comparators (hier: VergleicheHits) kann festgelegt werden, wie die Objekte verglichen werden sollen. Im Beispiel werden die Website-Objekte dann anhand ihrer Zugriffzahlen verglichen.

Klasse: Website

package de.fenon.Website;
 
/**
 * Informationen über Webseite.
 * @author fenon.de
 */
public class Website {
  /** Zahl der Besucher der Website. */
  private Integer hits;
 
  /**
   * Konstruktor.
   * @param besuche - Zahl der Besucher.
   */
  public Website(final Integer besuche) {
    this.setHits(besuche);
  } // ENDE: Konstruktor
 
  /**
   * Gibt die Besucherzahl der Webseite aus.
   * @return Zahl der Besucher der Website.
   */
  public final Integer getHits() {
    return hits;
  } // ENDE: getHits()
 
  /**
   * Setze die Besucherzahl der Webseite.
   * @param besuche - Zahl der Besucher.
   */
  public final void setHits(final Integer besuche) {
    this.hits = besuche;
  } // ENDE: setHits()
 
} // ENDE: Website

Comparator: VergleicheHits

package de.fenon.Website;
 
import java.util.Comparator;
 
/**
 * Vergleiche Website-Objekte anhand ihrer Hits.
 * @author fenon.de
 */
public class VergleicheHits implements Comparator<Website> {
  /** Konstruktor. */
  public VergleicheHits() {}
 
  @Override
  public final int compare(final Website a, final Website b) {
    if (a.getHits() < b.getHits()) {
      return -1;
    } else if (a.getHits().equals(b.getHits())) {
      return 0;
    } else {
      return 1;
    }
  } // ENDE: compare()
 
} // ENDE: VergleicheHits

Das Beispiel

package de.fenon.test;
 
import java.util.ArrayList;
import java.util.Collections;
import java.util.Random;
 
import de.fenon.Website.VergleicheHits;
import de.fenon.Website.Website;
 
/**
 * Beispiel: Kleinsten und größten Wert in einer Liste finden.
 * @author fenon.de
 */
public final class HauptProgramm {
  /** Zahl der Messungen. */
  static final Integer STICHPROBE = 10;
  /** Maximalwert. */
  static final Integer MAXIMUM = 10;
  /** Seed des Zufallszahlen-Generators. */
  static final Integer SEED = 1234567891;
 
  /**
   * Privater Konstruktor.
   * Dadurch kann kein Objekt der Klasse "Hauptprogramm" erzeugt werden.
   */
  private HauptProgramm() {}
 
  /**
   * main()-Methode.
   * @param args - Parameter der Kommandozeile.
   */
  public static void main(final String[] args) {
    ArrayList<Website> seiten = new ArrayList<Website>();
    // Erzeuge zufällige Messwerte
    Random generator = new Random(SEED);
    for (int i = 0; i < STICHPROBE; i++) {
      seiten.add(new Website(generator.nextInt(MAXIMUM)));
    }
    // Gib die Messwerte aus
    for (Website element:seiten) {
      System.out.println("Hits: " + element.getHits());
    }
    // Gib Kleinsten und Größten Wert aus.
    // Mit einem anderen Getter könnte man z.B. den Namen der Website ausgeben.
    System.out.println(
      "Maximum: "
      + Collections.max(seiten, new VergleicheHits()).getHits()
      );
    System.out.println(
      "Minimum: "
      + Collections.min(seiten, new VergleicheHits()).getHits()
      );
  } // ENDE: main()
 
} // ENDE: HauptProgramm

Leidenschaftliche Karotten

Es ist ganz schön schwer einen Titel für die folgenden Bilder zu finden. „Porno mit Gemüse“, „Möhren Minne„, „Karotten Kopulation“, „Amors Wurzeln“ oder „Schmutzige Sachen, die Möhren so machen“. Im Prinzip sind es einfach zwei Karotten, die sich gern hatten – bis zum 25.09.2013. An jenem Mittwoch Abend habe ich beide an ihrem Kopfschmuck aus der Erde unseres Gartens in Göttingen gezogen und damit das Schäferstündchen jäh beendet. Bis dahin wusste ich allerdings auch nicht, was Möhren in der Dunkelheit so alles treiben.

Querformat_4854

Querformat_4856

Hochformat_4838

Hochformat_4858

Querformat_4849

Querformat_4857

Querformat_4859

Lustiges Obst und Gemüse gibt es auch hier: