01: /*
02: * (c) Copyright 2006 by Volker Bergmann. All rights reserved.
03: *
04: * Redistribution and use in source and binary forms, with or without
05: * modification, is permitted under the terms of the
06: * GNU General Public License.
07: *
08: * For redistributing this software or a derivative work under a license other
09: * than the GPL-compatible Free Software License as defined by the Free
10: * Software Foundation or approved by OSI, you must first obtain a commercial
11: * license to this software product from Volker Bergmann.
12: *
13: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14: * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
15: * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
16: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
17: * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24: * POSSIBILITY OF SUCH DAMAGE.
25: */
26:
27: package org.databene.measure.count;
28:
29: import java.util.*;
30: import java.util.concurrent.atomic.AtomicInteger;
31:
32: /**
33: * Counts objects.<br/><br/>
34: * Created: 14.12.2006 18:03:47
35: * @author Volker Bergmann
36: */
37: public class ObjectCounter<E> {
38: // TODO v0.4.2 move to an appropriate location
39: private Map<E, AtomicInteger> instances;
40: long totalCount;
41:
42: public ObjectCounter(int initialCapacity) {
43: instances = new HashMap<E, AtomicInteger>(initialCapacity);
44: totalCount = 0;
45: }
46:
47: // interface -------------------------------------------------------------------------------------------------------
48:
49: public void count(E instance) {
50: AtomicInteger counter = instances.get(instance);
51: if (counter == null)
52: instances.put(instance, new AtomicInteger(1));
53: else
54: counter.incrementAndGet();
55: totalCount++;
56: }
57:
58: public Set<E> objectSet() {
59: return instances.keySet();
60: }
61:
62: public int getCount(E instance) {
63: AtomicInteger counter = instances.get(instance);
64: return (counter != null ? counter.intValue() : 0);
65: }
66:
67: public double averageCount() {
68: return totalCount / instances.size();
69: }
70:
71: public boolean equalDistribution(double tolerance) {
72: double average = averageCount();
73: Collection<AtomicInteger> counts = instances.values();
74: for (AtomicInteger count : counts) {
75: if (Math.abs((count.doubleValue() - average) / average) > tolerance)
76: return false;
77: }
78: return true;
79: }
80:
81: @Override
82: public String toString() {
83: StringBuilder buffer = new StringBuilder("[");
84: Iterator<Map.Entry<E, AtomicInteger>> iterator = instances
85: .entrySet().iterator();
86: if (iterator.hasNext()) {
87: Map.Entry entry = iterator.next();
88: buffer.append(entry.getKey()).append(':').append(
89: entry.getValue());
90: }
91: while (iterator.hasNext()) {
92: Map.Entry entry = iterator.next();
93: buffer.append(", ").append(entry.getKey()).append(':')
94: .append(entry.getValue());
95: }
96: buffer.append(']');
97: return buffer.toString();
98: }
99: }
|