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