From c295821d8593b21acc75373aff5469e0b2bbbbf2 Mon Sep 17 00:00:00 2001 From: "J. Neugebauer" Date: Sat, 16 Jul 2022 13:31:52 +0200 Subject: [PATCH] Timer und Counter Hilfsklassen --- src/main/java/schule/ngb/zm/util/Counter.java | 145 ++++++++++++++++++ src/main/java/schule/ngb/zm/util/Timer.java | 81 ++++++++++ .../java/schule/ngb/zm/util/CounterTest.java | 98 ++++++++++++ 3 files changed, 324 insertions(+) create mode 100644 src/main/java/schule/ngb/zm/util/Counter.java create mode 100644 src/main/java/schule/ngb/zm/util/Timer.java create mode 100644 src/test/java/schule/ngb/zm/util/CounterTest.java diff --git a/src/main/java/schule/ngb/zm/util/Counter.java b/src/main/java/schule/ngb/zm/util/Counter.java new file mode 100644 index 0000000..61299fd --- /dev/null +++ b/src/main/java/schule/ngb/zm/util/Counter.java @@ -0,0 +1,145 @@ +package schule.ngb.zm.util; + +import java.util.Collection; +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; + +@SuppressWarnings( "unused" ) +public final class Counter { + + public static Counter fromArray( double[] values ) { + return new Counter().countAll(values); + } + + public static Counter fromArray( Number[] values ) { + return new Counter().countAll(values); + } + + public static Counter fromList( List values ) { + return new Counter().countAll(values); + } + + private AtomicInteger count = new AtomicInteger(0); + + private double min = Double.NaN, max = Double.NaN, sum = Double.NaN; + + public void Counter() { + + } + + public void Counter( int initial ) { + count.set(initial); + } + + public int getCount() { + return count.get(); + } + + public double getMax() { + synchronized( count ) { + return max; + } + } + + public double getMin() { + synchronized( count ) { + return min; + } + } + + public double getSum() { + synchronized( count ) { + return sum; + } + } + + public double getAvg() { + if( Double.isNaN(sum) ) { + return Double.NaN; + } else { + return sum / count.doubleValue(); + } + } + + public Counter setCount( int count ) { + this.count.set(count); + return this; + } + + @SuppressWarnings( "UnusedReturnValue" ) + public Counter reset() { + count.set(0); + synchronized( count ) { + min = Double.NaN; + max = Double.NaN; + sum = Double.NaN; + } + return this; + } + + @SuppressWarnings( "UnusedReturnValue" ) + public Counter inc() { + this.count.incrementAndGet(); + return this; + } + + @SuppressWarnings( "UnusedReturnValue" ) + public Counter dec() { + this.count.decrementAndGet(); + return this; + } + + @SuppressWarnings( "UnusedReturnValue" ) + public Counter count( double value ) { + inc(); + // Update stats + synchronized( count ) { + sum = Double.isNaN(sum) ? value : sum + value; + if( Double.isNaN(max) || max < value ) + max = value; + if( Double.isNaN(min) ||min > value ) + min = value; + } + return this; + } + + @SuppressWarnings( "UnusedReturnValue" ) + public Counter count( Number num ) { + return count(num.doubleValue()); + } + + @SuppressWarnings( "UnusedReturnValue" ) + public Counter count( Object obj ) { + if( obj instanceof Number ) { + return count((Number) obj); + } else { + inc(); + return this; + } + } + + @SuppressWarnings( "UnusedReturnValue" ) + public synchronized Counter countAll( double[] values ) { + for( double value: values ) { + count(value); + } + return this; + } + + @SuppressWarnings( "UnusedReturnValue" ) + public synchronized Counter countAll( Number[] values ) { + for( Number value: values ) { + count(value); + } + return this; + } + + @SuppressWarnings( "UnusedReturnValue" ) + public synchronized Counter countAll( Collection values ) { + for( Number value: values ) { + count(value); + } + return this; + } + +} diff --git a/src/main/java/schule/ngb/zm/util/Timer.java b/src/main/java/schule/ngb/zm/util/Timer.java new file mode 100644 index 0000000..fdfcd64 --- /dev/null +++ b/src/main/java/schule/ngb/zm/util/Timer.java @@ -0,0 +1,81 @@ +package schule.ngb.zm.util; + +import java.util.concurrent.TimeUnit; + +@SuppressWarnings( "unused" ) +public final class Timer { + + private final TimeUnit baseUnit; + + private boolean running = false; + + private long starttime = -1; + + private long elapsed = 0; + + public Timer() { + this(TimeUnit.MILLISECONDS); + } + + public Timer( TimeUnit baseUnit ) { + this.baseUnit = baseUnit; + } + + public boolean isRunning() { + return running; + } + + @SuppressWarnings( "UnusedReturnValue" ) + public Timer start() { + starttime = System.nanoTime(); + running = true; + + return this; + } + + @SuppressWarnings( "UnusedReturnValue" ) + public Timer stop() { + running = false; + elapsed += System.nanoTime() - starttime; + + return this; + } + + @SuppressWarnings( "UnusedReturnValue" ) + public Timer reset() { + running = false; + starttime = -1; + elapsed = 0; + + return this; + } + + public long getTime() { + return getTime(baseUnit); + } + + public long getTime( TimeUnit unit ) { + if( running ) { + return unit.convert(System.nanoTime() - starttime + elapsed, TimeUnit.NANOSECONDS); + } else { + return unit.convert(elapsed, TimeUnit.NANOSECONDS); + } + } + + public int getMillis() { + if( running ) { + return (int) ((System.nanoTime() - starttime + elapsed) / 1000000); + } else { + return (int) (elapsed / 1000000); + } + } + + public double getSeconds() { + if( running ) { + return (System.nanoTime() - starttime + elapsed) / 1000000000.0; + } else { + return elapsed / 1000000000.0; + } + } + +} diff --git a/src/test/java/schule/ngb/zm/util/CounterTest.java b/src/test/java/schule/ngb/zm/util/CounterTest.java new file mode 100644 index 0000000..8fc6b30 --- /dev/null +++ b/src/test/java/schule/ngb/zm/util/CounterTest.java @@ -0,0 +1,98 @@ +package schule.ngb.zm.util; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class CounterTest { + + @Test + void counter() { + Counter cnt = new Counter(); + assertEquals(0, cnt.getCount()); + assertEquals(Double.NaN, cnt.getMax()); + assertEquals(Double.NaN, cnt.getMin()); + assertEquals(Double.NaN, cnt.getSum()); + } + + @Test + void getCount() { + Counter cnt = new Counter(); + assertEquals(0, cnt.getCount()); + cnt.inc(); + assertEquals(1, cnt.getCount()); + cnt.inc(); cnt.inc(); + assertEquals(3, cnt.getCount()); + cnt.setCount(33); + assertEquals(33, cnt.getCount()); + } + + @Test + void getMax() { + Counter cnt = new Counter(); + assertEquals(Double.NaN, cnt.getMax()); + cnt.count(2); + assertEquals(2, cnt.getMax()); + cnt.count(8); + assertEquals(8, cnt.getMax()); + cnt.count(4); + assertEquals(8, cnt.getMax()); + } + + @Test + void getMin() { + Counter cnt = new Counter(); + assertEquals(Double.NaN, cnt.getMin()); + cnt.count(2); + assertEquals(2, cnt.getMin(), "min(2)"); + cnt.count(8); + assertEquals(2, cnt.getMin(), "min(2,8)"); + cnt.count(1); + assertEquals(1, cnt.getMin(), "min(2,8,1)"); + } + + @Test + void getSum() { + Counter cnt = new Counter(); + assertEquals(Double.NaN, cnt.getSum()); + cnt.count(2); + assertEquals(2, cnt.getSum()); + cnt.count(8); + assertEquals(10, cnt.getSum()); + cnt.count(-1); + assertEquals(9, cnt.getSum()); + } + + @Test + void reset() { + Counter cnt = new Counter(); + cnt.inc(); + cnt.count(2); + assertEquals(2, cnt.getCount()); + assertEquals(2, cnt.getSum()); + cnt.reset(); + assertEquals(0, cnt.getCount()); + assertEquals(Double.NaN, cnt.getSum()); + } + + @Test + void inc() { + Counter cnt = new Counter(); + assertEquals(0, cnt.getCount()); + cnt.inc(); + assertEquals(1, cnt.getCount()); + cnt.inc().inc(); + assertEquals(3, cnt.getCount()); + } + + @Test + void dec() { + Counter cnt = new Counter(); + assertEquals(0, cnt.getCount()); + cnt.dec(); + assertEquals(-1, cnt.getCount()); + cnt.dec().dec(); + assertEquals(-3, cnt.getCount()); + } + +}