1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.modeshape.common.statistic;
25
26 import java.util.concurrent.locks.Lock;
27 import java.util.concurrent.locks.ReadWriteLock;
28 import java.util.concurrent.locks.ReentrantReadWriteLock;
29 import net.jcip.annotations.ThreadSafe;
30 import org.modeshape.common.math.MathOperations;
31 import org.modeshape.common.text.Inflector;
32 import org.modeshape.common.util.StringUtil;
33
34
35
36
37
38
39
40
41
42
43
44
45
46 @ThreadSafe
47 public class SimpleStatistics<T extends Number> {
48
49 protected final MathOperations<T> math;
50 private int count = 0;
51 private T total;
52 private T maximum;
53 private T minimum;
54 private T mean;
55 private Double meanValue;
56 private final ReadWriteLock lock = new ReentrantReadWriteLock();
57
58 public SimpleStatistics( MathOperations<T> operations ) {
59 this.math = operations;
60 this.total = this.math.createZeroValue();
61 this.maximum = this.math.createZeroValue();
62 this.minimum = null;
63 this.mean = this.math.createZeroValue();
64 this.meanValue = 0.0d;
65 }
66
67
68
69
70
71
72 public void add( T value ) {
73 Lock lock = this.lock.writeLock();
74 try {
75 lock.lock();
76 doAddValue(value);
77 } finally {
78 lock.unlock();
79 }
80 }
81
82
83
84
85
86
87
88 protected void doAddValue( T value ) {
89 if (value == null) return;
90
91 ++this.count;
92 this.total = math.add(this.total, value);
93 this.maximum = this.math.maximum(this.maximum, value);
94 this.minimum = this.math.minimum(this.minimum, value);
95
96 int count = getCount();
97 if (count == 1) {
98
99 this.meanValue = value.doubleValue();
100 this.mean = value;
101 } else {
102 double dValue = value.doubleValue();
103 double dCount = count;
104
105 this.meanValue = this.meanValue + ((dValue - this.meanValue) / dCount);
106 this.mean = this.math.create(this.meanValue);
107 }
108 }
109
110
111
112
113
114
115 public T getTotal() {
116 Lock lock = this.lock.readLock();
117 lock.lock();
118 try {
119 return this.total;
120 } finally {
121 lock.unlock();
122 }
123 }
124
125
126
127
128
129
130 public T getMaximum() {
131 Lock lock = this.lock.readLock();
132 lock.lock();
133 try {
134 return this.maximum;
135 } finally {
136 lock.unlock();
137 }
138 }
139
140
141
142
143
144
145 public T getMinimum() {
146 Lock lock = this.lock.readLock();
147 lock.lock();
148 try {
149 return this.minimum != null ? this.minimum : (T)this.math.createZeroValue();
150 } finally {
151 lock.unlock();
152 }
153 }
154
155
156
157
158
159
160 public int getCount() {
161 Lock lock = this.lock.readLock();
162 lock.lock();
163 try {
164 return this.count;
165 } finally {
166 lock.unlock();
167 }
168 }
169
170
171
172
173
174
175
176 public T getMean() {
177 Lock lock = this.lock.readLock();
178 lock.lock();
179 try {
180 return this.mean;
181 } finally {
182 lock.unlock();
183 }
184 }
185
186
187
188
189
190
191
192 public double getMeanValue() {
193 Lock lock = this.lock.readLock();
194 lock.lock();
195 try {
196 return this.meanValue;
197 } finally {
198 lock.unlock();
199 }
200 }
201
202
203
204
205 public void reset() {
206 Lock lock = this.lock.writeLock();
207 lock.lock();
208 try {
209 doReset();
210 } finally {
211 lock.unlock();
212 }
213 }
214
215 public MathOperations<T> getMathOperations() {
216 return math;
217 }
218
219 protected ReadWriteLock getLock() {
220 return this.lock;
221 }
222
223
224
225
226
227 protected void doReset() {
228 this.total = this.math.createZeroValue();
229 this.maximum = this.math.createZeroValue();
230 this.minimum = null;
231 this.mean = this.math.createZeroValue();
232 this.meanValue = 0.0d;
233 this.count = 0;
234 }
235
236 @Override
237 public String toString() {
238 int count = this.getCount();
239 String samples = Inflector.getInstance().pluralize("sample", count);
240 return StringUtil.createString("{0} {1}: min={2}; avg={3}; max={4}",
241 count,
242 samples,
243 this.minimum,
244 this.mean,
245 this.maximum);
246 }
247
248 }