• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  *******************************************************************************
3  * Copyright (C) 1996-2001, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  *
7  * $Revision: 13987 $
8  *
9  *******************************************************************************
10  */
11 
12 package org.unicode.cldr.util;
13 
14 import java.util.Collection;
15 import java.util.Comparator;
16 import java.util.Iterator;
17 import java.util.LinkedHashMap;
18 import java.util.LinkedHashSet;
19 import java.util.Map;
20 import java.util.Set;
21 import java.util.TreeMap;
22 import java.util.TreeSet;
23 
24 import com.ibm.icu.impl.Row;
25 import com.ibm.icu.impl.Row.R2;
26 
27 public class Counter<T> implements Iterable<T>, Comparable<Counter<T>> {
28     Map<T, RWLong> map;
29     Comparator<T> comparator;
30 
Counter()31     public Counter() {
32         this(null);
33     }
34 
Counter(boolean naturalOrdering)35     public Counter(boolean naturalOrdering) {
36         this(naturalOrdering ? new CldrUtility.ComparableComparator() : null);
37     }
38 
Counter(Comparator<T> comparator)39     public Counter(Comparator<T> comparator) {
40         if (comparator != null) {
41             this.comparator = comparator;
42             map = new TreeMap<T, RWLong>(comparator);
43         } else {
44             map = new LinkedHashMap<T, RWLong>();
45         }
46     }
47 
48     static private final class RWLong implements Comparable<RWLong> {
49         // the uniqueCount ensures that two different RWIntegers will always be different
50         static int uniqueCount;
51         public long value;
52         private final int forceUnique;
53         public long time;
54         {
55             synchronized (RWLong.class) { // make thread-safe
56                 forceUnique = uniqueCount++;
57             }
58         }
59 
compareTo(RWLong that)60         public int compareTo(RWLong that) {
61             if (that.value < value) return -1;
62             if (that.value > value) return 1;
63             if (this == that) return 0;
64             synchronized (this) { // make thread-safe
65                 if (that.forceUnique < forceUnique) return -1;
66             }
67             return 1; // the forceUnique values must be different, so this is the only remaining case
68         }
69 
toString()70         public String toString() {
71             return String.valueOf(value);
72         }
73 
74     }
75 
add(T obj, long countValue)76     public Counter<T> add(T obj, long countValue) {
77         RWLong count = map.get(obj);
78         if (count == null) map.put(obj, count = new RWLong());
79         count.value += countValue;
80         count.time = 0;
81         return this;
82     }
83 
add(T obj, long countValue, long time)84     public Counter<T> add(T obj, long countValue, long time) {
85         RWLong count = map.get(obj);
86         if (count == null) map.put(obj, count = new RWLong());
87         count.value += countValue;
88         count.time = time;
89         return this;
90     }
91 
add(T obj, long countValue, boolean boo)92     public Counter<T> add(T obj, long countValue, boolean boo) {
93         RWLong count = map.get(obj);
94         if (count == null) map.put(obj, count = new RWLong());
95         count.value = countValue;
96         count.time = 0;
97         return this;
98     }
99 
getCount(T obj)100     public long getCount(T obj) {
101         return get(obj);
102     }
103 
get(T obj)104     public long get(T obj) {
105         RWLong count = map.get(obj);
106         return count == null ? 0 : count.value;
107     }
108 
109     /**
110      * Get the time, or 0
111      * @param obj
112      * @return the time, or 0 as a fallback
113      */
getTime(T obj)114     public final long getTime(T obj) {
115         RWLong count = map.get(obj);
116         return count == null ? 0 : count.time;
117     }
118 
clear()119     public Counter<T> clear() {
120         map.clear();
121         return this;
122     }
123 
getTotal()124     public long getTotal() {
125         long count = 0;
126         for (T item : map.keySet()) {
127             count += map.get(item).value;
128         }
129         return count;
130     }
131 
getItemCount()132     public int getItemCount() {
133         return size();
134     }
135 
136     private static class Entry<T> {
137         RWLong count;
138         T value;
139         int uniqueness;
140 
Entry(RWLong count, T value, int uniqueness)141         public Entry(RWLong count, T value, int uniqueness) {
142             this.count = count;
143             this.value = value;
144             this.uniqueness = uniqueness;
145         }
146     }
147 
148     private static class EntryComparator<T> implements Comparator<Entry<T>> {
149         int countOrdering;
150         Comparator<T> byValue;
151 
EntryComparator(boolean ascending, Comparator<T> byValue)152         public EntryComparator(boolean ascending, Comparator<T> byValue) {
153             countOrdering = ascending ? 1 : -1;
154             this.byValue = byValue;
155         }
156 
compare(Entry<T> o1, Entry<T> o2)157         public int compare(Entry<T> o1, Entry<T> o2) {
158             if (o1.count.value < o2.count.value) return -countOrdering;
159             if (o1.count.value > o2.count.value) return countOrdering;
160             if (byValue != null) {
161                 return byValue.compare(o1.value, o2.value);
162             }
163             return o1.uniqueness - o2.uniqueness;
164         }
165     }
166 
getKeysetSortedByCount(boolean ascending)167     public Set<T> getKeysetSortedByCount(boolean ascending) {
168         return getKeysetSortedByCount(ascending, null);
169     }
170 
getKeysetSortedByCount(boolean ascending, Comparator<T> byValue)171     public Set<T> getKeysetSortedByCount(boolean ascending, Comparator<T> byValue) {
172         Set<Entry<T>> count_key = new TreeSet<Entry<T>>(new EntryComparator<T>(ascending, byValue));
173         int counter = 0;
174         for (T key : map.keySet()) {
175             count_key.add(new Entry<T>(map.get(key), key, counter++));
176         }
177         Set<T> result = new LinkedHashSet<T>();
178         for (Entry<T> entry : count_key) {
179             result.add(entry.value);
180         }
181         return result;
182     }
183 
getEntrySetSortedByCount(boolean ascending, Comparator<T> byValue)184     public Set<Row.R2<Long, T>> getEntrySetSortedByCount(boolean ascending, Comparator<T> byValue) {
185         Set<Entry<T>> count_key = new TreeSet<Entry<T>>(new EntryComparator<T>(ascending, byValue));
186         int counter = 0;
187         for (T key : map.keySet()) {
188             count_key.add(new Entry<T>(map.get(key), key, counter++));
189         }
190         Set<R2<Long, T>> result = new LinkedHashSet<Row.R2<Long, T>>();
191         for (Entry<T> entry : count_key) {
192             result.add(Row.of(entry.count.value, entry.value));
193         }
194         return result;
195     }
196 
getKeysetSortedByKey()197     public Set<T> getKeysetSortedByKey() {
198         Set<T> s = new TreeSet<T>(comparator);
199         s.addAll(map.keySet());
200         return s;
201     }
202 
203     // public Map<T,RWInteger> getKeyToKey() {
204     // Map<T,RWInteger> result = new HashMap<T,RWInteger>();
205     // Iterator<T> it = map.keySet().iterator();
206     // while (it.hasNext()) {
207     // Object key = it.next();
208     // result.put(key, key);
209     // }
210     // return result;
211     // }
212 
keySet()213     public Set<T> keySet() {
214         return map.keySet();
215     }
216 
iterator()217     public Iterator<T> iterator() {
218         return map.keySet().iterator();
219     }
220 
getMap()221     public Map<T, RWLong> getMap() {
222         return map; // older code was protecting map, but not the integer values.
223     }
224 
size()225     public int size() {
226         return map.size();
227     }
228 
toString()229     public String toString() {
230         return map.toString();
231     }
232 
addAll(Collection<T> keys, int delta)233     public Counter<T> addAll(Collection<T> keys, int delta) {
234         for (T key : keys) {
235             long time = getTime(key);
236             add(key, delta, time);
237         }
238         return this;
239     }
240 
addAll(Counter<T> keys)241     public Counter<T> addAll(Counter<T> keys) {
242         for (T key : keys) {
243             long time = getTime(key);
244             add(key, keys.getCount(key), time);
245         }
246         return this;
247     }
248 
compareTo(Counter<T> o)249     public int compareTo(Counter<T> o) {
250         Iterator<T> i = map.keySet().iterator();
251         Iterator<T> j = o.map.keySet().iterator();
252         while (true) {
253             boolean goti = i.hasNext();
254             boolean gotj = j.hasNext();
255             if (!goti || !gotj) {
256                 return goti ? 1 : gotj ? -1 : 0;
257             }
258             T ii = i.next();
259             T jj = i.next();
260             int result = ((Comparable<T>) ii).compareTo(jj);
261             if (result != 0) {
262                 return result;
263             }
264             final long iv = map.get(ii).value;
265             final long jv = o.map.get(jj).value;
266             if (iv != jv) return iv < jv ? -1 : 0;
267         }
268     }
269 
increment(T key)270     public Counter<T> increment(T key) {
271         return add(key, 1, getTime(key));
272     }
273 
containsKey(T key)274     public boolean containsKey(T key) {
275         return map.containsKey(key);
276     }
277 
equals(Object o)278     public boolean equals(Object o) {
279         return map.equals(o);
280     }
281 
hashCode()282     public int hashCode() {
283         return map.hashCode();
284     }
285 
isEmpty()286     public boolean isEmpty() {
287         return map.isEmpty();
288     }
289 
remove(T key)290     public Counter<T> remove(T key) {
291         map.remove(key);
292         return this;
293     }
294 
295     // public RWLong put(T key, RWLong value) {
296     // return map.put(key, value);
297     // }
298     //
299     // public void putAll(Map<? extends T, ? extends RWLong> t) {
300     // map.putAll(t);
301     // }
302     //
303     // public Set<java.util.Map.Entry<T, Long>> entrySet() {
304     // return map.entrySet();
305     // }
306     //
307     // public Collection<RWLong> values() {
308     // return map.values();
309     // }
310 
311 }