Support null values in StringMap
This commit is contained in:
parent
ad3489f557
commit
751c69c655
@ -29,7 +29,8 @@ import java.util.Set;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A map of strings to values. Like LinkedHashMap, this map's iteration order is
|
* A map of strings to values. Like LinkedHashMap, this map's iteration order is
|
||||||
* well defined: it is the order that elements were inserted into the map.
|
* well defined: it is the order that elements were inserted into the map. This
|
||||||
|
* map does not support null keys.
|
||||||
*
|
*
|
||||||
* <p>This implementation was derived from Android 4.0's LinkedHashMap.
|
* <p>This implementation was derived from Android 4.0's LinkedHashMap.
|
||||||
*/
|
*/
|
||||||
@ -98,32 +99,33 @@ public final class StringMap<K, V> extends AbstractMap<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override public boolean containsKey(Object key) {
|
@Override public boolean containsKey(Object key) {
|
||||||
return get(key) != null;
|
return getEntry(key) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public V get(Object key) {
|
@Override public V get(Object key) {
|
||||||
|
LinkedEntry<K, V> entry = getEntry(key);
|
||||||
|
return entry != null ? entry.value : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private LinkedEntry<K, V> getEntry(Object key) {
|
||||||
if (key == null) {
|
if (key == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doug Lea's supplemental secondaryHash function (inlined)
|
int hash = secondaryHash(key.hashCode());
|
||||||
int hash = key.hashCode();
|
|
||||||
hash ^= (hash >>> 20) ^ (hash >>> 12);
|
|
||||||
hash ^= (hash >>> 7) ^ (hash >>> 4);
|
|
||||||
|
|
||||||
LinkedEntry<K, V>[] tab = table;
|
LinkedEntry<K, V>[] tab = table;
|
||||||
for (LinkedEntry<K, V> e = tab[hash & (tab.length - 1)]; e != null; e = e.next) {
|
for (LinkedEntry<K, V> e = tab[hash & (tab.length - 1)]; e != null; e = e.next) {
|
||||||
K eKey = e.key;
|
K eKey = e.key;
|
||||||
if (eKey == key || (e.hash == hash && key.equals(eKey))) {
|
if (eKey == key || (e.hash == hash && key.equals(eKey))) {
|
||||||
return e.value;
|
return e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public V put(K key, V value) {
|
@Override public V put(K key, V value) {
|
||||||
if (key == null || value == null) {
|
if (key == null) {
|
||||||
throw new IllegalArgumentException();
|
throw new NullPointerException("key == null");
|
||||||
}
|
}
|
||||||
|
|
||||||
int hash = secondaryHash(key.hashCode());
|
int hash = secondaryHash(key.hashCode());
|
||||||
@ -311,9 +313,6 @@ public final class StringMap<K, V> extends AbstractMap<K, V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public final V setValue(V value) {
|
public final V setValue(V value) {
|
||||||
if (value == null) {
|
|
||||||
throw new IllegalArgumentException();
|
|
||||||
}
|
|
||||||
V oldValue = this.value;
|
V oldValue = this.value;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
return oldValue;
|
return oldValue;
|
||||||
@ -324,7 +323,9 @@ public final class StringMap<K, V> extends AbstractMap<K, V> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Entry<?, ?> e = (Entry<?, ?>) o;
|
Entry<?, ?> e = (Entry<?, ?>) o;
|
||||||
return key.equals(e.getKey()) && value.equals(e.getValue());
|
Object eValue = e.getValue();
|
||||||
|
return key.equals(e.getKey())
|
||||||
|
&& (value == null ? eValue == null : value.equals(eValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public final int hashCode() {
|
@Override public final int hashCode() {
|
||||||
@ -341,7 +342,7 @@ public final class StringMap<K, V> extends AbstractMap<K, V> {
|
|||||||
* exists; otherwise, returns does nothing and returns false.
|
* exists; otherwise, returns does nothing and returns false.
|
||||||
*/
|
*/
|
||||||
private boolean removeMapping(Object key, Object value) {
|
private boolean removeMapping(Object key, Object value) {
|
||||||
if (key == null || value == null) {
|
if (key == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +351,7 @@ public final class StringMap<K, V> extends AbstractMap<K, V> {
|
|||||||
int index = hash & (tab.length - 1);
|
int index = hash & (tab.length - 1);
|
||||||
for (LinkedEntry<K, V> e = tab[index], prev = null; e != null; prev = e, e = e.next) {
|
for (LinkedEntry<K, V> e = tab[index], prev = null; e != null; prev = e, e = e.next) {
|
||||||
if (e.hash == hash && key.equals(e.key)) {
|
if (e.hash == hash && key.equals(e.key)) {
|
||||||
if (!value.equals(e.value)) {
|
if (value == null ? e.value != null : !value.equals(e.value)) {
|
||||||
return false; // Map has wrong value for key
|
return false; // Map has wrong value for key
|
||||||
}
|
}
|
||||||
if (prev == null) {
|
if (prev == null) {
|
||||||
|
@ -63,6 +63,7 @@ public final class ObjectTypeAdapter extends TypeAdapter<Object> {
|
|||||||
return list;
|
return list;
|
||||||
|
|
||||||
case BEGIN_OBJECT:
|
case BEGIN_OBJECT:
|
||||||
|
// TODO: string map doesn't support null values
|
||||||
Map<String, Object> map = new StringMap<String, Object>();
|
Map<String, Object> map = new StringMap<String, Object>();
|
||||||
in.beginObject();
|
in.beginObject();
|
||||||
while (in.hasNext()) {
|
while (in.hasNext()) {
|
||||||
|
@ -18,6 +18,7 @@ package com.google.gson;
|
|||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
@ -38,6 +39,18 @@ public final class ObjectTypeAdapterTest extends TestCase {
|
|||||||
assertEquals("{'a':5,'b':[1,2,null]}", adapter.toJson(object).replace("\"", "'"));
|
assertEquals("{'a':5,'b':[1,2,null]}", adapter.toJson(object).replace("\"", "'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSerializeNullValue() throws Exception {
|
||||||
|
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||||
|
map.put("a", null);
|
||||||
|
assertEquals("{'a':null}", adapter.toJson(map).replace('"', '\''));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testDeserializeNullValue() throws Exception {
|
||||||
|
Map<String, Object> map = new LinkedHashMap<String, Object>();
|
||||||
|
map.put("a", null);
|
||||||
|
assertEquals(map, adapter.fromJson("{\"a\":null}"));
|
||||||
|
}
|
||||||
|
|
||||||
public void testSerializeObject() throws Exception {
|
public void testSerializeObject() throws Exception {
|
||||||
assertEquals("{}", adapter.toJson(new Object()));
|
assertEquals("{}", adapter.toJson(new Object()));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user