1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.archive.util;
29
30 import java.util.Comparator;
31 import java.util.HashMap;
32 import java.util.Map;
33 import java.util.TreeSet;
34
35
36 /***
37 * Collect and report frequency information.
38 *
39 * Assumes external synchornization.
40 *
41 * @author gojomo
42 */
43 public class Histotable<K> extends HashMap<K,Long> {
44 private static final long serialVersionUID = 310306238032568623L;
45
46 /***
47 * Record one more occurence of the given object key.
48 *
49 * @param key Object key.
50 */
51 public void tally(K key) {
52 tally(key,1L);
53 }
54
55 /***
56 * Record <i>count</i> more occurence(s) of the given object key.
57 *
58 * @param key Object key.
59 */
60 public void tally(K key,long count) {
61 if (containsKey(key)) {
62 put(key,get(key) + count);
63 } else {
64
65 put(key, count);
66 }
67 }
68
69 /***
70 * @return Return an up-to-date sorted version of the totalled info.
71 */
72 public TreeSet getSortedByCounts() {
73
74 TreeSet<Map.Entry<K,Long>> sorted =
75 new TreeSet<Map.Entry<K,Long>>(
76 new Comparator<Map.Entry<K,Long>>() {
77 public int compare(Map.Entry<K,Long> e1,
78 Map.Entry<K,Long> e2) {
79 long firstVal = e1.getValue();
80 long secondVal = e2.getValue();
81 if (firstVal < secondVal) { return 1; }
82 if (secondVal < firstVal) { return -1; }
83
84 String firstKey = (String) ((Map.Entry) e1).getKey();
85 String secondKey = (String) ((Map.Entry) e2).getKey();
86 return firstKey.compareTo(secondKey);
87 }
88 });
89
90 sorted.addAll(entrySet());
91 return sorted;
92 }
93
94 /***
95 * @return Return an up-to-date sorted version of the totalled info.
96 */
97 public TreeSet getSortedByKeys() {
98 TreeSet<Map.Entry<K,Long>> sorted =
99 new TreeSet<Map.Entry<K,Long>>(
100 new Comparator<Map.Entry<K,Long>>() {
101 @SuppressWarnings("unchecked")
102 public int compare(Map.Entry<K,Long> e1,
103 Map.Entry<K,Long> e2) {
104 K firstKey = e1.getKey();
105 K secondKey = e2.getKey();
106
107 return ((Comparable<K>)firstKey).compareTo(secondKey);
108 }
109 });
110 sorted.addAll(entrySet());
111 return sorted;
112 }
113
114 /***
115 * Return the largest value of any key that is larger than 0. If no
116 * values or no value larger than zero, return zero.
117 *
118 * @return long largest value or zero if none larger than zero
119 */
120 public long getLargestValue() {
121 long largest = 0;
122 for (Long el : values()) {
123 if (el > largest) {
124 largest = el;
125 }
126 }
127 return largest;
128 }
129
130 /***
131 * Return the total of all tallies.
132 *
133 * @return long total of all tallies
134 */
135 public long getTotal() {
136 long total = 0;
137 for (Long el : values()) {
138 total += el;
139 }
140 return total;
141 }
142
143 /***
144 * Utility method to convert a key->Long into
145 * the string "count key".
146 *
147 * @param e Map key.
148 * @return String 'count key'.
149 */
150 public static String entryString(Object e) {
151 Map.Entry entry = (Map.Entry) e;
152 return entry.getValue() + " " + entry.getKey();
153 }
154
155 public long add(Histotable<K> ht) {
156 long net = 0;
157 for (K key : ht.keySet()) {
158 long change = ht.get(key);
159 net += change;
160 tally(key,change);
161 }
162 return net;
163 }
164 public long subtract(Histotable<K> ht) {
165 long net = 0;
166 for (K key : ht.keySet()) {
167 long change = ht.get(key);
168 net -= change;
169 tally(key,-change);
170 }
171 return net;
172 }
173 }