AbstractMap.java 6.12 KB
Newer Older
1 2 3 4 5 6 7 8 9
/* AbstractMap.java -- Abstract implementation of most of Map
   Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
10

11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA.

As a special exception, if you link this library with other files to
produce an executable, this library does not by itself cause the
resulting executable to be covered by the GNU General Public License.
This exception does not however invalidate any other reasons why the
executable file might be covered by the GNU General Public License. */


// TO DO:
// comments
// test suite

package java.util;

34 35 36 37 38 39 40 41 42 43 44
public abstract class AbstractMap implements Map
{
  /**
   * Remove all entries from this Map. This default implementation calls
   * entrySet().clear().
   *
   * @throws UnsupportedOperationException
   * @specnote The JCL book claims that this implementation always throws 
   *           UnsupportedOperationException, while the online docs claim it
   *           calls entrySet().clear(). We take the later to be correct.
   */
45 46 47 48 49
  public void clear()
  {
    entrySet().clear();
  }

50
  public boolean containsKey(Object key)
51 52
  {
    Object k;
53 54 55 56 57 58 59 60 61
    Set es = entrySet();
    Iterator entries = es.iterator();
    int size = size();
    for (int pos = 0; pos < size; pos++)
      {
	k = ((Map.Entry) entries.next()).getKey();
	if (key == null ? k == null : key.equals(k))
	  return true;
      }
62 63 64
    return false;
  }

65
  public boolean containsValue(Object value)
66 67
  {
    Object v;
68 69 70 71 72 73 74 75 76 77
    Set es = entrySet();
    Iterator entries = es.iterator();
    int size = size();
    for (int pos = 0; pos < size; pos++)
      {
	v = ((Map.Entry) entries.next()).getValue();
	if (value == null ? v == null : value.equals(v))
	  return true;
      }
    return false;
78 79 80 81
  }

  public abstract Set entrySet();

82
  public boolean equals(Object o)
83
  {
84
    if (o == this)
85
      return true;
86
    if (!(o instanceof Map))
87
      return false;
88 89 90 91 92 93 94

    Map m = (Map) o;
    Set s = m.entrySet();
    Iterator itr = entrySet().iterator();
    int size = size();

    if (m.size() != size)
95
      return false;
96 97 98 99 100 101 102

    for (int pos = 0; pos < size; pos++)
      {
	if (!s.contains(itr.next()))
	  return false;
      }
    return true;
103 104
  }

105
  public Object get(Object key)
106
  {
107 108 109 110 111 112 113 114 115 116 117
    Set s = entrySet();
    Iterator entries = s.iterator();
    int size = size();

    for (int pos = 0; pos < size; pos++)
      {
	Map.Entry entry = (Map.Entry) entries.next();
	Object k = entry.getKey();
	if (key == null ? k == null : key.equals(k))
	  return entry.getValue();
      }
118 119 120 121 122 123 124

    return null;
  }

  public int hashCode()
  {
    int hashcode = 0;
125 126 127 128 129 130
    Iterator itr = entrySet().iterator();
    int size = size();
    for (int pos = 0; pos < size; pos++)
      {
	hashcode += itr.next().hashCode();
      }
131 132 133 134 135 136 137 138 139 140
    return hashcode;
  }

  public boolean isEmpty()
  {
    return size() == 0;
  }

  public Set keySet()
  {
141 142 143
    if (this.keySet == null)
      {
	this.keySet = new AbstractSet()
144 145
	{
	  public int size()
146
	  {
147 148 149 150 151 152 153
	    return AbstractMap.this.size();
	  }

	  public boolean contains(Object key)
	  {
	    return AbstractMap.this.containsKey(key);
	  }
154

155
	  public Iterator iterator()
156
	  {
157
	    return new Iterator()
158
	    {
159
	      Iterator map_iterator = AbstractMap.this.entrySet().iterator();
160

161
	      public boolean hasNext()
162
	      {
163 164 165 166
		return map_iterator.hasNext();
	      }

	      public Object next()
167 168
	      {
		return ((Map.Entry) map_iterator.next()).getKey();
169
	      }
170

171
	      public void remove()
172
	      {
173 174 175 176 177
		map_iterator.remove();
	      }
	    };
	  }
	};
178 179 180
      }

    return this.keySet;
181 182
  }

183
  public Object put(Object key, Object value)
184 185 186 187
  {
    throw new UnsupportedOperationException();
  }

188
  public void putAll(Map m)
189 190 191
  {
    Map.Entry entry;
    Iterator entries = m.entrySet().iterator();
192 193 194 195 196 197 198
    int size = m.size();

    for (int pos = 0; pos < size; pos++)
      {
	entry = (Map.Entry) entries.next();
	put(entry.getKey(), entry.getValue());
      }
199 200
  }

201
  public Object remove(Object key)
202 203
  {
    Iterator entries = entrySet().iterator();
204 205 206
    int size = size();

    for (int pos = 0; pos < size; pos++)
207
      {
208 209 210 211 212 213 214 215
	Map.Entry entry = (Map.Entry) entries.next();
	Object k = entry.getKey();
	if (key == null ? k == null : key.equals(k))
	  {
	    Object value = entry.getValue();
	    entries.remove();
	    return value;
	  }
216 217
      }

218
    return null;
219 220 221 222 223 224 225 226 227 228
  }

  public int size()
  {
    return entrySet().size();
  }

  public String toString()
  {
    Iterator entries = entrySet().iterator();
229
    int size = size();
230
    StringBuffer r = new StringBuffer("{");
231 232
    for (int pos = 0; pos < size; pos++)
      {
233 234 235 236
        // Append the toString value of the entries rather than calling 
	// getKey/getValue. This is more efficient and it matches the JDK
	// behaviour.
	r.append(entries.next());	
237
	if (pos < size - 1)
238
	  r.append(", ");
239
      }
240 241
    r.append("}");
    return r.toString();
242 243 244 245
  }

  public Collection values()
  {
246 247 248
    if (this.valueCollection == null)
      {
	this.valueCollection = new AbstractCollection()
249 250
	{
	  public int size()
251
	  {
252 253
	    return AbstractMap.this.size();
	  }
254

255
	  public Iterator iterator()
256
	  {
257
	    return new Iterator()
258
	    {
259
	      Iterator map_iterator = AbstractMap.this.entrySet().iterator();
260

261
	      public boolean hasNext()
262
	      {
263 264 265 266
		return map_iterator.hasNext();
	      }

	      public Object next()
267 268
	      {
		return ((Map.Entry) map_iterator.next()).getValue();
269
	      }
270

271
	      public void remove()
272
	      {
273 274 275 276 277
		map_iterator.remove();
	      }
	    };
	  }
	};
278 279
      }

280 281 282 283 284 285
    return this.valueCollection;
  }

  private Collection valueCollection = null;
  private Set keySet = null;
}