|
@@ -12,12 +12,17 @@ import java.util.HashMap;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
import java.util.Map.Entry;
|
|
import java.util.Map.Entry;
|
|
|
import java.util.TreeMap;
|
|
import java.util.TreeMap;
|
|
|
|
|
+import java.util.WeakHashMap;
|
|
|
|
|
+import java.util.concurrent.ConcurrentHashMap;
|
|
|
import net.ranides.assira.reflection.ClassInspector;
|
|
import net.ranides.assira.reflection.ClassInspector;
|
|
|
import net.ranides.assira.reflection.Invoker;
|
|
import net.ranides.assira.reflection.Invoker;
|
|
|
|
|
+import net.ranides.assira.reflection.ObjectInspector;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
*
|
|
*
|
|
|
* @author Mariusz Sieron <m.sieron@samsung.com>
|
|
* @author Mariusz Sieron <m.sieron@samsung.com>
|
|
|
|
|
+ * @param <K>
|
|
|
|
|
+ * @param <V>
|
|
|
*/
|
|
*/
|
|
|
public class Column<K,V> {
|
|
public class Column<K,V> {
|
|
|
|
|
|
|
@@ -46,45 +51,91 @@ public class Column<K,V> {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public static <K,V> Entry<K,V> entry(Map<K, V> map, K key) {
|
|
public static <K,V> Entry<K,V> entry(Map<K, V> map, K key) {
|
|
|
- // @todo (assira # 5) MapEntry#get - support
|
|
|
|
|
- // - EnumMap
|
|
|
|
|
- // - WeakHashMap
|
|
|
|
|
- // - ConcurrentHashMap
|
|
|
|
|
- // - ConcurrentSkipListMap $SubMap
|
|
|
|
|
- // - TreeMap.NavigableSubMap
|
|
|
|
|
- // - IdentityHashMap
|
|
|
|
|
- // - assira.xml.NodeCollection.LMap
|
|
|
|
|
-
|
|
|
|
|
- if( map.isEmpty() ) {
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
- if(map instanceof TreeMap<?,?>) {
|
|
|
|
|
|
|
+ if(map instanceof TreeMap) {
|
|
|
return (Map.Entry<K,V>)Invoker.invoke(map, EntryAccess.TREE, key);
|
|
return (Map.Entry<K,V>)Invoker.invoke(map, EntryAccess.TREE, key);
|
|
|
}
|
|
}
|
|
|
- if(map instanceof HashMap<?,?>) {
|
|
|
|
|
|
|
+ if(EntryAccess.CS_TREE_SUBMAP.isInstance(map)) {
|
|
|
|
|
+ Object treemap = ObjectInspector.getField(EntryAccess.CS_TREE_SUBMAP, map, "m");
|
|
|
|
|
+ return (Map.Entry<K,V>)Invoker.invoke(treemap, EntryAccess.TREE, key);
|
|
|
|
|
+ }
|
|
|
|
|
+ if(map instanceof HashMap) {
|
|
|
return (Map.Entry<K,V>)Invoker.invoke(map, EntryAccess.HASH, key);
|
|
return (Map.Entry<K,V>)Invoker.invoke(map, EntryAccess.HASH, key);
|
|
|
}
|
|
}
|
|
|
- return new EntryView<K, V>(map, key);
|
|
|
|
|
|
|
+ if(map instanceof WeakHashMap) {
|
|
|
|
|
+ return (Map.Entry<K,V>)Invoker.invoke(map, EntryAccess.WEAK, key);
|
|
|
|
|
+ }
|
|
|
|
|
+ // it's slower than default "virtual" entry
|
|
|
|
|
+// if(map instanceof ConcurrentHashMap) {
|
|
|
|
|
+// return new CHEntry<K,V>(map, key);
|
|
|
|
|
+// }
|
|
|
|
|
+ return new DVEntry<K, V>(map, key);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private static final class EntryAccess {
|
|
private static final class EntryAccess {
|
|
|
|
|
|
|
|
private static final Method TREE;
|
|
private static final Method TREE;
|
|
|
private static final Method HASH;
|
|
private static final Method HASH;
|
|
|
|
|
+ private static final Method WEAK;
|
|
|
|
|
+
|
|
|
|
|
+ private static final Method CH_SEGMENT;
|
|
|
|
|
+ private static final Method CH_HASH;
|
|
|
|
|
+ private static final Method CH_GET;
|
|
|
|
|
+ private static final Method CH_PUT;
|
|
|
|
|
+
|
|
|
|
|
+ private static final Class<?> CS_TREE_SUBMAP;
|
|
|
|
|
|
|
|
static {
|
|
static {
|
|
|
TREE = ClassInspector.findDeclaredMethod(TreeMap.class, "getEntry");
|
|
TREE = ClassInspector.findDeclaredMethod(TreeMap.class, "getEntry");
|
|
|
|
|
+ CS_TREE_SUBMAP = ClassInspector.forName("java.util.TreeMap$NavigableSubMap");
|
|
|
|
|
+
|
|
|
HASH = ClassInspector.findDeclaredMethod(HashMap.class, "getEntry");
|
|
HASH = ClassInspector.findDeclaredMethod(HashMap.class, "getEntry");
|
|
|
|
|
+ WEAK = ClassInspector.findDeclaredMethod(WeakHashMap.class, "getEntry");
|
|
|
|
|
+
|
|
|
|
|
+ CH_SEGMENT = ClassInspector.getDeclaredMethod(ConcurrentHashMap.class, "segmentFor", int.class);
|
|
|
|
|
+ CH_HASH = ClassInspector.getDeclaredMethod(ConcurrentHashMap.class, "hash", int.class);
|
|
|
|
|
+
|
|
|
|
|
+ Class<?> CS_SEGMENT = ClassInspector.forName("java.util.concurrent.ConcurrentHashMap$Segment");
|
|
|
|
|
+ CH_GET = ClassInspector.findDeclaredMethod(CS_SEGMENT, "get");
|
|
|
|
|
+ CH_PUT = ClassInspector.findDeclaredMethod(CS_SEGMENT, "put");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static final class CHEntry<K,V> implements Map.Entry<K, V> {
|
|
|
|
|
+
|
|
|
|
|
+ private final K key;
|
|
|
|
|
+ private final int hash;
|
|
|
|
|
+ private final Object segment;
|
|
|
|
|
+
|
|
|
|
|
+ public CHEntry(Map<K,V> map, K key) {
|
|
|
|
|
+ this.key = key;
|
|
|
|
|
+ this.hash = (Integer)Invoker.invoke(null, EntryAccess.CH_HASH, key.hashCode());
|
|
|
|
|
+ this.segment = Invoker.invoke(map, EntryAccess.CH_SEGMENT, hash);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public K getKey() {
|
|
|
|
|
+ return key;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V getValue() {
|
|
|
|
|
+ return (V)Invoker.invoke(segment, EntryAccess.CH_GET, key, hash);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public V setValue(V value) {
|
|
|
|
|
+ return (V)Invoker.invoke(segment, EntryAccess.CH_PUT, key, hash, value, false);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- private static final class EntryView<K,V> implements Map.Entry<K, V> {
|
|
|
|
|
|
|
+ private static final class DVEntry<K,V> implements Map.Entry<K, V> {
|
|
|
|
|
|
|
|
private final Map<K,V> map;
|
|
private final Map<K,V> map;
|
|
|
private final K key;
|
|
private final K key;
|
|
|
|
|
|
|
|
- public EntryView(Map<K, V> map, K key) {
|
|
|
|
|
|
|
+ public DVEntry(Map<K, V> map, K key) {
|
|
|
this.map = map;
|
|
this.map = map;
|
|
|
this.key = key;
|
|
this.key = key;
|
|
|
}
|
|
}
|