diff --git a/src/main/java/schule/ngb/zm/util/Counter.java b/src/main/java/schule/ngb/zm/util/Counter.java index 61299fd..4922b1c 100644 --- a/src/main/java/schule/ngb/zm/util/Counter.java +++ b/src/main/java/schule/ngb/zm/util/Counter.java @@ -4,33 +4,101 @@ import java.util.Collection; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; +/** + * Eine Hilfsklasse um Dinge zu zählen. + *
+ * Im einfachsten Fall kann der Zähler als geteilte Zählvariable genutzt werden, + * die mit {@link #inc()} und {@link #dec()} aus verschiedenen Objekten oder + * Methoden verändert werden kann. + *
+ * Der Zähler kann aber auch Objekte zählen, indem die Instanzen an + * {@link #count(Object)} übergeben werden. Am Ende kann mit {@link #getCount()} + * die Anzahl der Objkete abgerufen werden. + *
+ * Handelt es sich bei den Objekten um Zahlen, dann merkt sich ein Zähler auch + * das Maximum, das Minimum, die Summe und den Durchschnitt der gezählten + * Werte. + *
+ * Ein Zähler kann auch komplette Arrays oder Listen von Zahlen zählen und die
+ * obigen Statistiken auswerten.
+ */
@SuppressWarnings( "unused" )
public final class Counter {
+ /**
+ * Erstellt einen neuen {@code Counter}, der alle Integer im angegebenen
+ * Array gezählt hat.
+ *
+ * @param values Die zu zählenden Werte.
+ * @return Ein neuer {@code Counter}.
+ */
+ public static Counter fromArray( int[] values ) {
+ return new Counter().countAll(values);
+ }
+
+ /**
+ * Erstellt einen neuen {@code Counter}, der alle Doubles im angegebenen
+ * Array gezählt hat.
+ *
+ * @param values Die zu zählenden Werte.
+ * @return Ein neuer {@code Counter}.
+ */
public static Counter fromArray( double[] values ) {
return new Counter().countAll(values);
}
+ /**
+ * Erstellt einen neuen {@code Counter}, der alle Zahlen im angegebenen
+ * Array gezählt hat.
+ *
+ * @param values Die zu zählenden Werte.
+ * @return Ein neuer {@code Counter}.
+ */
public static Counter fromArray( Number[] values ) {
return new Counter().countAll(values);
}
+ /**
+ * Erstellt einen neuen {@code Counter}, der alle Zahlen in der angegebenen
+ * Liste gezählt hat.
+ *
+ * @param values Die zu zählenden Werte.
+ * @return Ein neuer {@code Counter}.
+ */
public static Counter fromList( List
+ * Die Klasse kann zum Beispiel genutzt werden, um die Laufzeit eines
+ * Quelltextes zu messen. Wie eine echte Stoppuhr läuft der {@code Timer}
+ * weiter, wenn nach einem {@link #stop()} wieder {@link #start()} aufgerufen
+ * wird. Soll die Zeitmessung wieder bei null beginnen, muss vorher
+ * {@link #reset()} genutzt werden.
+ *
+ * Die gemessene Zeit kann in {@link #getMillis() Millisekunden} oder
+ * {@link #getSeconds() Sekunden} abgerufen werden. Wird eine noch größere
+ * Genauigkeit benötigt, können mit {@link #getTime(TimeUnit)} beliebige
+ * Zeiteinheiten (zum Beispiel {@link TimeUnit#NANOSECONDS Nanosekunden})
+ * abgerufen werden.
+ *
+ * Die Zeit kann auch bei laufender Uhr abgefragt werden. In dem Fall wird die
+ * bis zu diesem Zeitpunkt gemessene Zeit zurückgegeben.
+ */
@SuppressWarnings( "unused" )
public final class Timer {
+ /**
+ * Die Basiseinheit für die Zeitmessung.
+ */
private final TimeUnit baseUnit;
+ /**
+ * Ob die Zeitmessung gerade läuft.
+ */
private boolean running = false;
- private long starttime = -1;
+ /**
+ * Startzeit der Zeitmessung. -1, wenn noch keine Messung gestartet wurde.
+ */
+ private long start = -1;
+ /**
+ * Zeit, die bisher bei allen Zeitmessungen, die gestoppt wurden, insgesamt
+ * vergangen ist.
+ */
private long elapsed = 0;
+ /**
+ * Erstellt einen neuen {@code Timer} mit Millisekunden als Basiseinheit.
+ */
public Timer() {
this(TimeUnit.MILLISECONDS);
}
+ /**
+ * Erstellt einen {@code Timer}, der die angegebene Einheit als Basiseinheit
+ * für {@link #getTime()} benutzt.
+ *
+ * Um eine Zeitmessung in Nanosekunden durchzuführen, kann der {@code Timer}
+ * beispielsweise so instanziiert werden:
+ *
+ * Wenn zuvor schon eine Zeitmessung gestartet wurde, wird die neue Messung
+ * zur Summe aller Messungen hinzuaddiert. Soll die Messung bei null
+ * starten, muss vorher {@link #reset()} verwendet werden:
+ *
+ *
+ * Größere Zeiteinheiten werden gerundet und verlieren daher an Genauigkeit.
+ * Eine Zeitmessung von 999 Millisekunden wird als 0 Sekunden
+ * zurückgegeben.
+ *
+ * Um genauere Ergebnisse zu erhalten, kann mit {@link #getMillis()} und
+ * {@link #getSeconds()} die gemessene Zeit in Minuten beziehungsweise
+ * Sekunden als Kommazahl abgefragt werden.
+ *
+ * @param unit Zeiteinheit
+ * @return Die bisher insgesamt gemessene Zeit in der gewählten Zeiteinheit.
+ */
public long getTime( TimeUnit unit ) {
if( running ) {
- return unit.convert(System.nanoTime() - starttime + elapsed, TimeUnit.NANOSECONDS);
+ return unit.convert(System.nanoTime() - start + elapsed, TimeUnit.NANOSECONDS);
} else {
return unit.convert(elapsed, TimeUnit.NANOSECONDS);
}
}
+ /**
+ * Gibt die gemessene Zeit in Millisekunden (gerundet) zurück.
+ *
+ * @return Die gemessene Zeit in ms.
+ */
public int getMillis() {
if( running ) {
- return (int) ((System.nanoTime() - starttime + elapsed) / 1000000);
+ return (int) ((System.nanoTime() - start + elapsed) / 1000000);
} else {
return (int) (elapsed / 1000000);
}
}
+ /**
+ * Gibt die gemessene Zeit in Sekunden zurück.
+ *
+ * @return Die gemessene Zeit in s.
+ */
public double getSeconds() {
if( running ) {
- return (System.nanoTime() - starttime + elapsed) / 1000000000.0;
+ return (System.nanoTime() - start + elapsed) / 1000000000.0;
} else {
return elapsed / 1000000000.0;
}
+ *
+ * @param baseUnit Die Basiseinheit für die Zeitmessung.
+ */
public Timer( TimeUnit baseUnit ) {
this.baseUnit = baseUnit;
}
+ /**
+ * Ob die Zeitmessung gerade läuft.
+ *
+ * @return {@code true}, wenn die Zeitmessung mit {@link #start()} gestartet
+ * wurde.
+ */
public boolean isRunning() {
return running;
}
+ /**
+ * Startet die Zeitmessung.
+ *
+ * Timer clock = new Timer(TimeUnit.NANOSECONDS);
+ *
+ *
+ * @return Dieser {@code Timer} selbst (method chaining).
+ */
@SuppressWarnings( "UnusedReturnValue" )
public Timer start() {
- starttime = System.nanoTime();
+ start = System.nanoTime();
running = true;
return this;
}
+ /**
+ * Stoppt den {@code Timer}, wenn er derzeit läuft. Die gemessene Zeit wird
+ * zur Summe aller gemessenen Zeiten hinzuaddiert.
+ *
+ * @return Dieser {@code Timer} selbst (method chaining).
+ */
@SuppressWarnings( "UnusedReturnValue" )
public Timer stop() {
- running = false;
- elapsed += System.nanoTime() - starttime;
-
+ if( running ) {
+ running = false;
+ elapsed += System.nanoTime() - start;
+ }
return this;
}
+ /**
+ * Setzt den {@code Timer} auf den Startzustand und löscht alle bisher
+ * gemessenen Zeiten. Falls die Zeitmessung gerade läuft, wird sie nicht
+ * gestoppt, sondern läuft vom Zeitpunkt des Aufrufs weiter.
+ *
+ * @return Dieser {@code Timer} selbst (method chaining).
+ */
@SuppressWarnings( "UnusedReturnValue" )
public Timer reset() {
- running = false;
- starttime = -1;
elapsed = 0;
+ start = -1;
+
+ if( running ) {
+ start = System.nanoTime();
+ }
return this;
}
+ /**
+ * Gibt die Zeit in der Basiseinheit zurück.
+ *
+ * @return Die bisher insgesamt gemessene Zeit.
+ */
public long getTime() {
return getTime(baseUnit);
}
+ /**
+ * Gibt die Zeit in der angegebenen Einheit zurück.
+ *
+ * // Timer auf null stellen und sofort starten
+ * timer.reset().start();
+ *