logo

class

sys::Map

sys::Obj
  sys::Map
   1  //
   2  // Copyright (c) 2006, Brian Frank and Andy Frank
   3  // Licensed under the Academic Free License version 3.0
   4  //
   5  // History:
   6  //   30 Jan 06  Brian Frank  Creation
   7  //
   8  
   9  **
  10  ** Map is a hash map of key/value pairs.
  11  **
  12  final class Map
  13  {
  14  
  15  //////////////////////////////////////////////////////////////////////////
  16  // Constructor
  17  //////////////////////////////////////////////////////////////////////////
  18  
  19    **
  20    ** Constructor with of type (must be Map type).
  21    **
  22    new make(Type type)
  23  
  24  //////////////////////////////////////////////////////////////////////////
  25  // Identity
  26  //////////////////////////////////////////////////////////////////////////
  27  
  28    **
  29    ** Two Maps are equal if they have the same number of equal key/value pairs.
  30    **
  31    override Bool equals(Obj that)
  32  
  33    **
  34    ** Return platform dependent hashcode based on hash of the keys and values.
  35    **
  36    override Int hash()
  37  
  38  //////////////////////////////////////////////////////////////////////////
  39  // Methods
  40  //////////////////////////////////////////////////////////////////////////
  41  
  42    **
  43    ** Return if size() == 0.  This method is idempotent.
  44    **
  45    Bool isEmpty()
  46  
  47    **
  48    ** Get the number of key/value pairs in the list.  This
  49    ** method is idempotent.
  50    **
  51    Int size()
  52  
  53    **
  54    ** Get the value for the specified key.  If key is not
  55    ** mapped, then return the value of def (null by default).
  56    ** This method is idempotent.  Shortcut is a[key].
  57    **
  58    V get(K key, V def := null)
  59  
  60    **
  61    ** Return if the specified key is mapped.
  62    ** This method is idempotent.
  63    **
  64    Bool containsKey(K key)
  65  
  66    **
  67    ** Get a list of all the mapped keys.  This method is idempotent.
  68    **
  69    K[] keys()
  70  
  71    **
  72    ** Get a list of all the mapped values.  This method is idempotent.
  73    **
  74    V[] values()
  75  
  76    **
  77    ** Create a shallow duplicate copy of this Map.  The keys and
  78    ** values themselves are not duplicated.  This method is idempotent.
  79    **
  80    M dup()
  81  
  82    **
  83    ** Set the value for the specified key.  If the key is already
  84    ** mapped, this overwrites the old value.  If key is not yet mapped
  85    ** this adds the key/value pair to the map.  Return this.  If key
  86    ** does not return true for Obj.isImmutable, then throw NotImmutableErr.
  87    ** If key is null throw NullErr.  Throw ReadonlyErr if readonly.
  88    **
  89    M set(K key, V val)
  90  
  91    **
  92    ** Add the specified key/value pair to the map.  If the key is
  93    ** already mapped, then throw the ArgErr.  Return this.  If key
  94    ** does not return true for Obj.isImmutable, then throw NotImmutableErr.
  95    ** If key is null throw NullErr.  Throw ReadonlyErr if readonly.
  96    **
  97    M add(K key, V val)
  98  
  99    **
 100    ** Append the specified map to this map by setting every key/value in
 101    ** m in this map.  Keys in m not yet mapped are added and keys already
 102    ** mapped are overwritten.  Return this.  Throw ReadonlyErr if readonly.
 103    ** This method is semanatically equivalent to:
 104    **   m.each |K k, V v| { this.set(k, v) }
 105    **
 106    M setAll(M m)
 107  
 108    **
 109    ** Append the specified map to this map by adding every key/value in
 110    ** m in this map.  If any key in m is already mapped then this method
 111    ** will fail (any previous keys will remain mapped potentially leaving
 112    ** this map in an inconsistent state).  Return this.  Throw ReadonlyErr if
 113    ** readonly.  This method is semanatically equivalent to:
 114    **   m.each |K k, V v| { this.add(k, v) }
 115    **
 116    M addAll(M m)
 117  
 118    **
 119    ** Remove the key/value pair identified by the specified key
 120    ** from the map and return the value.   If the key was not mapped
 121    ** then return null.  Throw ReadonlyErr if readonly.
 122    **
 123    V remove(K key)
 124  
 125    **
 126    ** Remove all key/value pairs from the map.  Return this.
 127    ** Throw ReadonlyErr if readonly.
 128    **
 129    Void clear()
 130  
 131    **
 132    ** This field configures case sensitivity for maps with Str keys.  When
 133    ** set to true, Str keys are compared without regard to case for the following
 134    ** methods:  get, containsKey, set, add, setAll, addAll, and remove methods.
 135    ** Only ASCII character case is taken into account.  The original case
 136    ** is preserved (keys aren't made all lower or upper case).  This field
 137    ** defaults to false.
 138    **
 139    ** Getting this field is idempotent.  If you attempt to set this method
 140    ** on a map which is not empty or not typed to use Str keys, then throw
 141    ** UnsupportedOperation.  Throw ReadonlyErr if set when readonly.
 142    **
 143    Bool caseInsensitive := false
 144  
 145  //////////////////////////////////////////////////////////////////////////
 146  // Conversion
 147  //////////////////////////////////////////////////////////////////////////
 148  
 149    **
 150    ** Return a string representation the Map.  This method is idempotent.
 151    **
 152    override Str toStr()
 153  
 154  //////////////////////////////////////////////////////////////////////////
 155  // Iterators
 156  //////////////////////////////////////////////////////////////////////////
 157  
 158    **
 159    ** Call the specified function for every key/value in the list.
 160    ** This method is idempotent.
 161    **
 162    Void each(|V value, K key| c)
 163  
 164    **
 165    ** Return the first value in the map for which c returns true.
 166    ** If c returns false for every pair, then return null.  This
 167    ** method is idempotent.
 168    **
 169    V find(|V value, K key->Bool| c)
 170  
 171    **
 172    ** Return a new map containing the key/value pairs for which c
 173    ** returns true.  If c returns false for every item, then return
 174    ** an empty map.  The inverse of this method is exclude(). This
 175    ** method is idempotent.
 176    **
 177    M findAll(|V value, K key->Bool| c)
 178  
 179    **
 180    ** Return a new map containing the key/value pairs for which c
 181    ** returns false.  If c returns true for every item, then return
 182    ** an empty list.  The inverse of this method is findAll().  This
 183    ** method is idempotent.
 184    **
 185    ** Example:
 186    **   map := ["off":0, "slow":50, "fast":100]
 187    **   map.exclude |Int v->Bool| { return v == 0 } -> ["slow":50, "fast":100]
 188    **
 189    M exclude(|V item, K key->Bool| c)
 190  
 191    **
 192    ** Reduce is used to iterate through every value in the map
 193    ** to reduce the map into a single value called the reduction.
 194    ** The initial value of the reduction is passed in as the init
 195    ** parameter, then passed back to the closure along with each
 196    ** item.  This method is idempotent.
 197    **
 198    ** Example:
 199    **   m := ["2":2, "3":3, "4":4]
 200    **   m.reduce(100) |Obj r, Int v->Obj| { return (Int)r + v } -> 109
 201    **
 202    Obj reduce(Obj init, |Obj reduction, V item, K key->Obj| c)
 203  
 204    **
 205    ** Create a new map with the same keys, but apply the specified
 206    ** closure to generate new values.  This method is idempotent.
 207    **
 208    ** Example:
 209    **   m := [2:2, 3:3, 4:4]
 210    **   x := m.map(Str:Int[:]) |Int v->Obj| { return v*2 }
 211    **   x -> [2:4, 3:6, 4:8]
 212    **
 213    M map(Map acc, |V item, K key->Obj| c)
 214  
 215  //////////////////////////////////////////////////////////////////////////
 216  // Readonly
 217  //////////////////////////////////////////////////////////////////////////
 218  
 219    **
 220    ** Return if this Map is readonly.  A readonly Map is guaranteed
 221    ** to be immutable (although its values may be mutable themselves).
 222    ** Any attempt to modify a readonly Map will result in ReadonlyErr.
 223    ** Use rw() to get a read-write Map from a readonly Map.  Methods
 224    ** documented as idempotent may be used safely with a readonly Map.
 225    ** This method is idempotent.
 226    **
 227    Bool isRO()
 228  
 229    **
 230    ** Return if this Map is read-write.  A read-write Map is mutable
 231    ** and may be modified.  Use ro() to get a readonly Map from a
 232    ** read-write Map.  This method is idempotent.
 233    **
 234    Bool isRW()
 235  
 236    **
 237    ** Get a readonly, immutable Map instance with the same contents
 238    ** as this Map (although its values may be mutable themselves).
 239    ** If this Map is already readonly, then return this.  Only methods
 240    ** documented as idempotent may be used safely with a readonly
 241    ** Map, all others will throw ReadonlyErr.  This method is
 242    ** idempotent.
 243    **
 244    M ro()
 245  
 246    **
 247    ** Get a read-write, mutable Map instance with the same contents
 248    ** as this Map.  If this Map is already read-write, then return this.
 249    ** This method is idempotent.
 250    **
 251    M rw()
 252  
 253    **
 254    ** Return an immutable Map which returns true for Obj.isImmtable.
 255    ** If this Map is already immutable, then return this.  This method
 256    ** is effectively a "deep ro()" which guarantees that if any values
 257    ** are Lists or Maps, then they are made immutable by recursively calling
 258    ** toImmutable.  All other values must return true for Obj.isImmutable,
 259    ** otherwise NotImmutableErr is thrown.  This method must be used
 260    ** whenever setting a const Map field.  This method is idempotent.
 261    **
 262    M toImmutable()
 263  
 264  }