| SimpleMapImpl |

    1   /*
    2    *  SimpleMapImpl.java
    3    *
    4    *  Copyright (c) 2001, The University of Sheffield.
    5    *
    6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
    7    *  software, licenced under the GNU Library General Public License,
    8    *  Version 2, June 1991 (in the distribution as file licence.html,
    9    *  and also available at http://gate.ac.uk/gate/licence.html).
    10   *
    11   *  D.Ognyanoff, 5/Nov/2001
    12   *
    13   *  $Id: SimpleMapImpl.java,v 1.5 2001/11/20 12:25:51 kalina Exp $
    14   */
    15
    16  package gate.util;
    17
    18  import java.util.*;
    19
    20  /**
    21   * Implements Map interface in using less memory. Very simple but usefull
    22   * for small number of items on it.
    23   */
    24
    25  class SimpleMapImpl implements Map, java.lang.Cloneable, java.io.Serializable {
    26
    27    /**
    28     * The capacity of the map
    29     */
    30    int m_capacity=3;
    31
    32    /**
    33     * The current number of elements of the map
    34     */
    35    int m_size=0;
    36
    37    /**
    38     * Array keeping the keys of the entries in the map. It is "synchrnized"
    39     * with the m_values array - the Nth position in both arrays correspond
    40     * to one and the same entry
    41     */
    42    Object m_keys[];
    43    /**
    44     * Array keeping the values of the entries in the map. It is "synchrnized"
    45     * with the m_keys array - the Nth position in both arrays correspond
    46     * to one and the same entry
    47     */
    48    Object m_values[];
    49
    50    public SimpleMapImpl() {
    51      m_keys = new Object[m_capacity];
    52      m_values = new Object[m_capacity];
    53    }
    54
    55    public int size() {
    56      return m_size;
    57    }
    58
    59    public boolean isEmpty() {
    60      return (m_size == 0);
    61    }
    62
    63    public Collection values()
    64    {
    65      throw new UnsupportedOperationException(
    66        "SimpleMapImpl.values() not implemented!");
    67    }
    68
    69    public Set keySet()
    70    {
    71      HashSet s = new HashSet(size());
    72      Object k;
    73      for (int i=0; i<m_size; i++) {
    74        k = m_keys[i];
    75        if (k == nullKey)
    76             s.add(null);
    77          else
    78             s.add(k);
    79      } //for
    80      return s;
    81    } // keySet
    82
    83    public void clear()
    84    {
    85      for (int i=0; i<m_size; i++) {
    86        m_keys[i] = null;
    87        m_values[i] = null;
    88      } // for
    89      m_size =0;
    90    } // clear
    91
    92    public  boolean containsKey(Object key) {
    93      return (getPostionByKey(key) != -1);
    94    }// containsKey
    95
    96    public boolean containsValue(Object value) {
    97      return (getPostionByValue(value) != -1);
    98    }
    99
    100   public Object get(Object key) {
    101     int pos = getPostionByKey(key);
    102     return (pos == -1) ? null : m_values[pos];
    103   } // get
    104
    105   public Object put(Object key, Object value)
    106   {
    107     int pos = getPostionByKey(key);
    108     if (pos >= 0) {
    109       Object oldVal = m_values[pos];
    110       m_values[pos] = value;
    111       return oldVal;
    112     }
    113
    114     if (m_size == m_capacity)
    115       increaseCapacity();
    116
    117     if (g_akey == null)
    118         theKeysHere.put(key, key);
    119     else
    120         key = g_akey;
    121     m_keys[m_size] = key;
    122     m_values[m_size] = value;
    123     m_size++;
    124     return null;
    125   } // put
    126
    127   public Object remove(Object key)
    128   {
    129     int pos = getSubsumeKey((key==null)?nullKey:key);//getPostionByKey(key);
    130     if (pos == -1)
    131         return null;
    132
    133     Object oldVal = m_values[pos];
    134     m_size--;
    135     if (m_size != 0)
    136     {
    137         m_keys[pos] = m_keys[m_size];
    138         m_values[pos] = m_values[m_size];
    139     }
    140     m_keys[m_size] = null;
    141     m_values[m_size] = null;
    142
    143     return oldVal;
    144   } // remove
    145
    146   public void putAll(Map t)
    147   {
    148     if (t == null) {
    149       throw new UnsupportedOperationException(
    150       "SimpleMapImpl.putAll argument is null");
    151     }
    152
    153     if (t instanceof SimpleMapImpl) {
    154       SimpleMapImpl sfm = (SimpleMapImpl)t;
    155       Object key;
    156       for (int i=0; i<sfm.m_size; i++) {
    157           key = sfm.m_keys[i];
    158           put(key, sfm.m_values[i]);
    159       } //for
    160     } else {
    161       Iterator entries = t.entrySet().iterator();
    162       Map.Entry e;
    163       while (entries.hasNext()) {
    164         e = (Map.Entry)entries.next();
    165         put(e.getKey(), e.getValue());
    166       } // while
    167     } // if
    168   } // putAll
    169
    170 transient Object g_akey = null;
    171   private int getPostionByKey(Object key) {
    172     if (key == null)
    173         key = nullKey;
    174     g_akey = theKeysHere.get(key);
    175     if (g_akey == null)
    176         return -1;
    177
    178     for (int i=0; i<m_size; i++) {
    179       if (g_akey.equals(m_keys[i]))
    180           return i;
    181     } // for
    182     return -1;
    183   } // getPostionByKey
    184
    185   protected int getSubsumeKey(Object key) {
    186     for (int i=0; i<m_size; i++) {
    187       if (key == m_keys[i])
    188           return i;
    189     } // for
    190     return -1;
    191   } // getPostionByKey
    192
    193   private int getPostionByValue(Object value) {
    194     Object av;
    195     for (int i=0; i<m_size; i++) {
    196       av = m_values[i];
    197       if (value == null) {
    198         if (av == null)
    199           return i;
    200       }
    201       else
    202         if (value.equals(av))
    203             return i;
    204     } // for
    205
    206     return -1;
    207   } // getPostionByValue
    208
    209   // Modification Operations
    210   private void increaseCapacity()
    211   {
    212     int m_oldCapacity = m_capacity;
    213     m_capacity *= 2;
    214     Object m_oldKeys[] = m_keys;
    215     m_keys = new Object[m_capacity];
    216
    217     Object m_oldValues[] = m_values;
    218     m_values = new Object[m_capacity];
    219
    220     System.arraycopy(m_oldKeys, 0, m_keys, 0, m_oldCapacity);
    221     System.arraycopy(m_oldValues, 0, m_values, 0, m_oldCapacity);
    222   } // increaseCapacity
    223
    224   /**
    225    * Auxiliary classes needed for the support of entrySet() method
    226    */
    227   private static class Entry implements Map.Entry {
    228     int hash;
    229     Object key;
    230     Object value;
    231
    232     Entry(int hash, Object key, Object value) {
    233       this.hash = hash;
    234       this.key = key;
    235       this.value = value;
    236     }
    237
    238     protected Object clone() {
    239       return new Entry(hash, key, value);
    240     }
    241
    242     public Object getKey() {
    243       return key;
    244     }
    245
    246     public Object getValue() {
    247       return value;
    248     }
    249
    250     public Object setValue(Object value) {
    251       Object oldValue = this.value;
    252       this.value = value;
    253       return oldValue;
    254     }
    255
    256     public boolean equals(Object o) {
    257         if (!(o instanceof Map.Entry))
    258             return false;
    259         Map.Entry e = (Map.Entry)o;
    260
    261         return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
    262             (value==null ? e.getValue()==null : value.equals(e.getValue()));
    263     }
    264
    265     public int hashCode() {
    266         return hash ^ (key==null ? 0 : key.hashCode());
    267     }
    268
    269     public String toString() {
    270         return key+"="+value;
    271     }
    272   } // Entry
    273
    274
    275   public Set entrySet() {
    276     HashSet s = new HashSet(size());
    277     Object v, k;
    278     for (int i=0; i<m_size; i++) {
    279       k = m_keys[i];
    280       s.add(new Entry(k.hashCode(), ((k==nullKey)?null:k), m_values[i]));
    281     } //for
    282     return s;
    283   } // entrySet
    284
    285   // Comparison and hashing
    286
    287   public boolean equals(Object o) {
    288     if (!(o instanceof Map)) {
    289       return false;
    290     }
    291
    292     Map m = (Map)o;
    293     if (m.size() != m_size) {
    294       return false;
    295     }
    296
    297     Object v, k;
    298     for (int i=0; i<m_size; i++) {
    299       k = m_keys[i];
    300       v = m.get(k);
    301       if (v==null) {
    302         if (m_values[i]!=null)
    303           return false;
    304       }
    305       else if (!v.equals(m_values[i])){
    306         return false;
    307       }
    308     } // for
    309
    310     return true;
    311   } // equals
    312
    313   /*
    314   public int hashCode() {
    315     int hash=0;
    316     Object key;
    317     for (int i=0; i<m_capacity; i++) {
    318       key = m_keys[i];
    319       if (key == null)
    320       continue;
    321       HashMap hm;
    322       hash += m_keys[i].hashCode();
    323       hash += m_values[i].hashCode();
    324     } // for
    325
    326     return hash;
    327   } // hashCode
    328 */
    329
    330   public int hashCode() {
    331     int h = 0;
    332     Iterator i = entrySet().iterator();
    333     while (i.hasNext())
    334       h += i.next().hashCode();
    335     return h;
    336   }
    337
    338
    339   public Object clone() {
    340     SimpleMapImpl newMap;
    341     try {
    342       newMap = (SimpleMapImpl)super.clone();
    343     } catch (CloneNotSupportedException e) {
    344       throw(new InternalError(e.toString()));
    345     }
    346
    347     newMap.m_size = m_size;
    348     newMap.m_keys = new Object[m_capacity];
    349     System.arraycopy(m_keys, 0, newMap.m_keys, 0, m_capacity);
    350
    351     newMap.m_values = new Object[m_capacity];
    352     System.arraycopy(m_values, 0, newMap.m_values, 0, m_capacity);
    353
    354     return newMap;
    355   } // clone
    356
    357   public String toString() {
    358     int max = size() - 1;
    359     StringBuffer buf = new StringBuffer();
    360     Iterator i = entrySet().iterator();
    361
    362     buf.append("{");
    363     for (int j = 0; j <= max; j++) {
    364         Entry e = (Entry) (i.next());
    365         buf.append(e.getKey() + "=" + e.getValue());
    366         if (j < max)
    367       buf.append(", ");
    368     }
    369     buf.append("}");
    370     return buf.toString();
    371   }
    372
    373
    374  /** Freeze the serialization UID. */
    375   static final long serialVersionUID = -6747241616127229116L;
    376
    377  /** the Object instance that will represent the NULL keys in the map */
    378   transient static Object nullKey = new Object();
    379   transient public static HashMap theKeysHere = new HashMap();
    380   static {
    381     theKeysHere.put(nullKey, nullKey);
    382   }
    383
    384   /** the static keys colleaction */
    385 } //SimpleMapImpl
    386

| SimpleMapImpl |