You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/07/12 13:50:59 UTC
[groovy] 01/01: Replace `Index` and `MethodIndex` with
`LinkedHashMap`
This is an automated email from the ASF dual-hosted git repository.
sunlan pushed a commit to branch GROOVY-9631
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 1dbde02fe6c5ebab0236480959e7eee6c80e035a
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Jul 12 21:50:25 2020 +0800
Replace `Index` and `MethodIndex` with `LinkedHashMap`
---
src/main/java/groovy/lang/MetaClassImpl.java | 117 +++++++++++----------
.../groovy-json/src/spec/test/json/JsonTest.groovy | 4 +-
.../test/groovy/groovy/json/JsonOutputTest.groovy | 28 ++---
3 files changed, 79 insertions(+), 70 deletions(-)
diff --git a/src/main/java/groovy/lang/MetaClassImpl.java b/src/main/java/groovy/lang/MetaClassImpl.java
index f26af35..4c16eb0 100644
--- a/src/main/java/groovy/lang/MetaClassImpl.java
+++ b/src/main/java/groovy/lang/MetaClassImpl.java
@@ -102,6 +102,7 @@ import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
@@ -147,13 +148,13 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
protected final boolean isMap;
protected final MetaMethodIndex metaMethodIndex;
- private final Index classPropertyIndex = new MethodIndex();
- private final SingleKeyHashMap staticPropertyIndex = new SingleKeyHashMap();
+ private final Map<CachedClass, LinkedHashMap<String, MetaProperty>> classPropertyIndex = new LinkedHashMap<>();
+ private final Map<String, MetaProperty> staticPropertyIndex = new LinkedHashMap<>();
private final Map<String, MetaMethod> listeners = new HashMap<>();
private final List<MetaMethod> allMethods = new ArrayList<>();
// we only need one of these that can be reused over and over.
private final MetaProperty arrayLengthProperty = new MetaArrayLengthProperty();
- private final Index classPropertyIndexForSuper = new MethodIndex();
+ private final Map<CachedClass, LinkedHashMap<String, MetaProperty>> classPropertyIndexForSuper = new LinkedHashMap<>();
private final Set<MetaMethod> newGroovyMethodsSet = new HashSet<>();
private final MetaMethod[] myNewMetaMethods;
private final MetaMethod[] additionalMetaMethods;
@@ -280,15 +281,15 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
* @see MetaObjectProtocol#getMetaProperty(String)
*/
public MetaProperty getMetaProperty(String name) {
- MetaProperty metaProperty = null;
+ MetaProperty metaProperty;
- SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
- metaProperty = (MetaProperty) propertyMap.get(name);
+ LinkedHashMap<String, MetaProperty> propertyMap = classPropertyIndex.computeIfAbsent(theCachedClass, k -> new LinkedHashMap<>());
+ metaProperty = propertyMap.get(name);
if (metaProperty == null) {
- metaProperty = (MetaProperty) staticPropertyIndex.get(name);
+ metaProperty = staticPropertyIndex.get(name);
if (metaProperty == null) {
- propertyMap = classPropertyIndexForSuper.getNotNull(theCachedClass);
- metaProperty = (MetaProperty) propertyMap.get(name);
+ propertyMap = classPropertyIndexForSuper.computeIfAbsent(theCachedClass, k -> new LinkedHashMap<>());
+ metaProperty = propertyMap.get(name);
if (metaProperty == null) {
MetaBeanProperty property = findPropertyInClassHierarchy(name, theCachedClass);
if (property != null) {
@@ -1623,7 +1624,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
};
l.sort(comp);
int found = -1;
- for (int i = 0; i < l.size(); i++) {
+ for (int i = 0, n = l.size(); i < n; i++) {
if (l.get(i) != constructor) continue;
found = i;
break;
@@ -2174,16 +2175,16 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
*/
public List<MetaProperty> getProperties() {
checkInitalised();
- SingleKeyHashMap propertyMap = classPropertyIndex.getNullable(theCachedClass);
+ LinkedHashMap<String, MetaProperty> propertyMap = classPropertyIndex.get(theCachedClass);
if (propertyMap == null) {
// GROOVY-6903: May happen in some special environment, like under Android, due
// to classloading issues
- propertyMap = new SingleKeyHashMap();
+ propertyMap = new LinkedHashMap<>();
}
// simply return the values of the metaproperty map as a List
- List ret = new ArrayList(propertyMap.size());
- for (ComplexKeyHashMap.EntryIterator iter = propertyMap.getEntrySetIterator(); iter.hasNext(); ) {
- MetaProperty element = (MetaProperty) ((SingleKeyHashMap.Entry) iter.next()).value;
+ List<MetaProperty> ret = new ArrayList<>(propertyMap.size());
+ for (Iterator<Map.Entry<String, MetaProperty>> iter = propertyMap.entrySet().iterator(); iter.hasNext(); ) {
+ MetaProperty element = iter.next().getValue();
if (element instanceof CachedField) continue;
// filter out DGM beans
if (element instanceof MetaBeanProperty) {
@@ -2345,9 +2346,9 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
superInterfaces.sort(CACHED_CLASS_NAME_COMPARATOR);
}
- SingleKeyHashMap iPropertyIndex = classPropertyIndex.getNotNull(theCachedClass);
+ Map<String, MetaProperty> iPropertyIndex = classPropertyIndex.computeIfAbsent(theCachedClass, k -> new LinkedHashMap<>());
for (CachedClass iclass : superInterfaces) {
- SingleKeyHashMap sPropertyIndex = classPropertyIndex.getNotNull(iclass);
+ Map<String, MetaProperty> sPropertyIndex = classPropertyIndex.computeIfAbsent(iclass, k -> new LinkedHashMap<>());
copyNonPrivateFields(sPropertyIndex, iPropertyIndex, null);
addFields(iclass, iPropertyIndex);
}
@@ -2368,7 +2369,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
// if this an Array, then add the special read-only "length" property
if (theCachedClass.isArray) {
- SingleKeyHashMap map = new SingleKeyHashMap();
+ LinkedHashMap<String, MetaProperty> map = new LinkedHashMap<>();
map.put("length", arrayLengthProperty);
classPropertyIndex.put(theCachedClass, map);
}
@@ -2387,11 +2388,11 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
}
private void makeStaticPropertyIndex() {
- SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
- for (ComplexKeyHashMap.EntryIterator iter = propertyMap.getEntrySetIterator(); iter.hasNext(); ) {
- SingleKeyHashMap.Entry entry = ((SingleKeyHashMap.Entry) iter.next());
+ LinkedHashMap<String, MetaProperty> propertyMap = classPropertyIndex.computeIfAbsent(theCachedClass, k -> new LinkedHashMap<>());
+ for (Iterator<Map.Entry<String, MetaProperty>> iter = propertyMap.entrySet().iterator(); iter.hasNext(); ) {
+ Map.Entry<String, MetaProperty> entry = iter.next();
- MetaProperty mp = (MetaProperty) entry.getValue();
+ MetaProperty mp = entry.getValue();
if (mp instanceof CachedField) {
CachedField mfp = (CachedField) mp;
if (!mfp.isStatic()) continue;
@@ -2458,32 +2459,30 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
return result;
}
- private void copyClassPropertyIndexForSuper(Index dest) {
- for (ComplexKeyHashMap.EntryIterator iter = classPropertyIndex.getEntrySetIterator(); iter.hasNext(); ) {
- SingleKeyHashMap.Entry entry = (SingleKeyHashMap.Entry) iter.next();
- SingleKeyHashMap newVal = new SingleKeyHashMap();
- dest.put((CachedClass) entry.getKey(), newVal);
+ private void copyClassPropertyIndexForSuper(Map<CachedClass, LinkedHashMap<String, MetaProperty>> dest) {
+ for (Iterator<Map.Entry<CachedClass, LinkedHashMap<String, MetaProperty>>> iter = classPropertyIndex.entrySet().iterator(); iter.hasNext(); ) {
+ Map.Entry<CachedClass, LinkedHashMap<String, MetaProperty>> entry = iter.next();
+ LinkedHashMap<String, MetaProperty> newVal = new LinkedHashMap<>();
+ dest.put(entry.getKey(), newVal);
}
}
- private void inheritStaticInterfaceFields(LinkedList superClasses, Set interfaces) {
- for (Object anInterface : interfaces) {
- CachedClass iclass = (CachedClass) anInterface;
- SingleKeyHashMap iPropertyIndex = classPropertyIndex.getNotNull(iclass);
+ private void inheritStaticInterfaceFields(List<CachedClass> superClasses, Set<CachedClass> interfaces) {
+ for (CachedClass iclass : interfaces) {
+ LinkedHashMap<String, MetaProperty> iPropertyIndex = classPropertyIndex.computeIfAbsent(iclass, k -> new LinkedHashMap<>());
addFields(iclass, iPropertyIndex);
- for (Object superClass : superClasses) {
- CachedClass sclass = (CachedClass) superClass;
- if (!iclass.getTheClass().isAssignableFrom(sclass.getTheClass())) continue;
- SingleKeyHashMap sPropertyIndex = classPropertyIndex.getNotNull(sclass);
+ for (CachedClass superClass : superClasses) {
+ if (!iclass.getTheClass().isAssignableFrom(superClass.getTheClass())) continue;
+ LinkedHashMap<String, MetaProperty> sPropertyIndex = classPropertyIndex.computeIfAbsent(superClass, k -> new LinkedHashMap<>());
copyNonPrivateFields(iPropertyIndex, sPropertyIndex, null);
}
}
}
private void inheritFields(LinkedList<CachedClass> superClasses) {
- SingleKeyHashMap last = null;
+ LinkedHashMap<String, MetaProperty> last = null;
for (CachedClass klass : superClasses) {
- SingleKeyHashMap propertyIndex = classPropertyIndex.getNotNull(klass);
+ LinkedHashMap<String, MetaProperty> propertyIndex = classPropertyIndex.computeIfAbsent(klass, k -> new LinkedHashMap<>());
if (last != null) {
copyNonPrivateFields(last, propertyIndex, klass);
}
@@ -2492,15 +2491,15 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
}
}
- private static void addFields(CachedClass klass, SingleKeyHashMap propertyIndex) {
+ private static void addFields(CachedClass klass, Map<String, MetaProperty> propertyIndex) {
for (CachedField field : klass.getFields()) {
propertyIndex.put(field.getName(), field);
}
}
- private static void copyNonPrivateFields(SingleKeyHashMap from, SingleKeyHashMap to, @Nullable CachedClass klass) {
- for (ComplexKeyHashMap.EntryIterator it = from.getEntrySetIterator(); it.hasNext(); ) {
- SingleKeyHashMap.Entry entry = (SingleKeyHashMap.Entry) it.next();
+ private static void copyNonPrivateFields(Map<String, MetaProperty> from, Map<String, MetaProperty> to, @Nullable CachedClass klass) {
+ for (Iterator<Map.Entry<String, MetaProperty>> it = from.entrySet().iterator(); it.hasNext(); ) {
+ Map.Entry<String, MetaProperty> entry = it.next();
CachedField field = (CachedField) entry.getValue();
int modifiers = field.getModifiers();
if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers) || (!Modifier.isPrivate(modifiers)
@@ -2510,11 +2509,11 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
}
}
- private void applyStrayPropertyMethods(LinkedList<CachedClass> superClasses, Index classPropertyIndex, boolean isThis) {
+ private void applyStrayPropertyMethods(LinkedList<CachedClass> superClasses, Map<CachedClass, LinkedHashMap<String, MetaProperty>> classPropertyIndex, boolean isThis) {
// now look for any stray getters that may be used to define a property
for (CachedClass klass : superClasses) {
MetaMethodIndex.Header header = metaMethodIndex.getHeader(klass.getTheClass());
- SingleKeyHashMap propertyIndex = classPropertyIndex.getNotNull(klass);
+ Map<String, MetaProperty> propertyIndex = classPropertyIndex.computeIfAbsent(klass, k -> new LinkedHashMap<>());
for (MetaMethodIndex.Entry e = header.head; e != null; e = e.nextClassEntry) {
String methodName = e.name;
// name too short?
@@ -2598,9 +2597,9 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
}
}
- private static void createMetaBeanProperty(SingleKeyHashMap propertyIndex, String propName, boolean isGetter, MetaMethod propertyMethod) {
+ private static void createMetaBeanProperty(Map<String, MetaProperty> propertyIndex, String propName, boolean isGetter, MetaMethod propertyMethod) {
// is this property already accounted for?
- MetaProperty mp = (MetaProperty) propertyIndex.get(propName);
+ MetaProperty mp = propertyIndex.get(propName);
MetaProperty newMp = makeReplacementMetaProperty(mp, propName, isGetter, propertyMethod);
if (newMp != mp) {
propertyIndex.put(propName, newMp);
@@ -2654,10 +2653,10 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
if (staticProperty != null) {
staticPropertyIndex.put(mp.getName(), mp);
} else {
- SingleKeyHashMap propertyMap = classPropertyIndex.getNotNull(theCachedClass);
+ LinkedHashMap<String, MetaProperty> propertyMap = classPropertyIndex.computeIfAbsent(theCachedClass, k -> new LinkedHashMap<>());
//keep field
CachedField field;
- MetaProperty old = (MetaProperty) propertyMap.get(mp.getName());
+ MetaProperty old = propertyMap.get(mp.getName());
if (old != null) {
if (old instanceof MetaBeanProperty) {
field = ((MetaBeanProperty) old).getField();
@@ -2851,13 +2850,13 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
CachedClass clazz = ReflectionCache.getCachedClass(_clazz);
while (true) {
- SingleKeyHashMap propertyMap;
+ Map<String, MetaProperty> propertyMap;
if (useStatic) {
propertyMap = staticPropertyIndex;
} else if (useSuper) {
- propertyMap = classPropertyIndexForSuper.getNullable(clazz);
+ propertyMap = classPropertyIndexForSuper.get(clazz);
} else {
- propertyMap = classPropertyIndex.getNullable(clazz);
+ propertyMap = classPropertyIndex.get(clazz);
}
if (propertyMap == null) {
if (clazz != theCachedClass) {
@@ -2867,22 +2866,22 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
return null;
}
}
- return (MetaProperty) propertyMap.get(name);
+ return propertyMap.get(name);
}
}
private MetaProperty getMetaProperty(String name, boolean useStatic) {
CachedClass clazz = theCachedClass;
- SingleKeyHashMap propertyMap;
+ Map<String, MetaProperty> propertyMap;
if (useStatic) {
propertyMap = staticPropertyIndex;
} else {
- propertyMap = classPropertyIndex.getNullable(clazz);
+ propertyMap = classPropertyIndex.get(clazz);
}
if (propertyMap == null) {
return null;
}
- return (MetaProperty) propertyMap.get(name);
+ return propertyMap.get(name);
}
/**
@@ -3902,6 +3901,7 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
metaMethodIndex.clearCaches();
}
+ @Deprecated
private static final SingleKeyHashMap.Copier NAME_INDEX_COPIER = value -> {
if (value instanceof FastArray) {
return ((FastArray) value).copy();
@@ -3910,8 +3910,13 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
}
};
+ @Deprecated
private static final SingleKeyHashMap.Copier METHOD_INDEX_COPIER = value -> SingleKeyHashMap.copy(new SingleKeyHashMap(false), (SingleKeyHashMap) value, NAME_INDEX_COPIER);
+ /**
+ * @deprecated use {@link LinkedHashMap} instead
+ */
+ @Deprecated
static class MethodIndex extends Index {
public MethodIndex(boolean b) {
super(false);
@@ -3934,6 +3939,10 @@ public class MetaClassImpl implements MetaClass, MutableMetaClass {
}
}
+ /**
+ * @deprecated use {@link LinkedHashMap} instead
+ */
+ @Deprecated
public static class Index extends SingleKeyHashMap {
public Index(int size) {
diff --git a/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy b/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy
index 1069af1..02b6863 100644
--- a/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy
+++ b/subprojects/groovy-json/src/spec/test/json/JsonTest.groovy
@@ -120,7 +120,7 @@ class JsonTest extends GroovyTestCase {
.excludeFieldsByType(URL)
.build()
- assert generator.toJson(person) == '{"dob":"1984@12","name":"John"}'
+ assert generator.toJson(person) == '{"name":"John","dob":"1984@12"}'
// end::json_output_generator[]
'''
}
@@ -148,7 +148,7 @@ class JsonTest extends GroovyTestCase {
}
.build()
- assert generator.toJson(person) == '{"favoriteUrl":"groovy-lang.org","name":"John"}'
+ assert generator.toJson(person) == '{"name":"John","favoriteUrl":"groovy-lang.org"}'
// No key available when generating a JSON Array
def list = [new URL('http://groovy-lang.org/json.html#_jsonoutput')]
diff --git a/subprojects/groovy-json/src/test/groovy/groovy/json/JsonOutputTest.groovy b/subprojects/groovy-json/src/test/groovy/groovy/json/JsonOutputTest.groovy
index 3ed54bf..20c061d 100644
--- a/subprojects/groovy-json/src/test/groovy/groovy/json/JsonOutputTest.groovy
+++ b/subprojects/groovy-json/src/test/groovy/groovy/json/JsonOutputTest.groovy
@@ -306,30 +306,30 @@ class JsonOutputTest extends GroovyTestCase {
"name": "Paris",
"districts": [
{
+ "number": 1,
"streets": [
{
- "kind": "street",
- "streetName": "Saint-Honore"
+ "streetName": "Saint-Honore",
+ "kind": "street"
},
{
- "kind": "avenue",
- "streetName": "de l'Opera"
+ "streetName": "de l'Opera",
+ "kind": "avenue"
}
- ],
- "number": 1
+ ]
},
{
+ "number": 2,
"streets": [
{
- "kind": "boulevard",
- "streetName": "des Italiens"
+ "streetName": "des Italiens",
+ "kind": "boulevard"
},
{
- "kind": "boulevard",
- "streetName": "Bonne Nouvelle"
+ "streetName": "Bonne Nouvelle",
+ "kind": "boulevard"
}
- ],
- "number": 2
+ ]
}
]
}'''.stripIndent()
@@ -350,12 +350,12 @@ class JsonOutputTest extends GroovyTestCase {
void testObjectWithDeclaredPropertiesField() {
def person = new JsonObject(name: "pillow", properties: [state: "fluffy", color: "white"])
def json = toJson(person)
- assert json == '{"properties":{"state":"fluffy","color":"white"},"name":"pillow"}'
+ assert json == '{"name":"pillow","properties":{"state":"fluffy","color":"white"}}'
}
void testGROOVY5494() {
def json = toJson(new JsonFoo(name: "foo"))
- assert json == '{"properties":0,"name":"foo"}'
+ assert json == '{"name":"foo","properties":0}'
}
void testCharacter() {