diff --git a/JSONArray.java b/JSONArray.java index d08586d0..531b89df 100644 --- a/JSONArray.java +++ b/JSONArray.java @@ -154,8 +154,10 @@ public JSONArray(String source) throws JSONException { * A Collection. */ public JSONArray(Collection collection) { - this.myArrayList = new ArrayList(); - if (collection != null) { + if (collection == null) { + this.myArrayList = new ArrayList(); + } else { + this.myArrayList = new ArrayList(collection.size()); for (Object o: collection){ this.myArrayList.add(JSONObject.wrap(o)); } @@ -172,6 +174,7 @@ public JSONArray(Object array) throws JSONException { this(); if (array.getClass().isArray()) { int length = Array.getLength(array); + this.myArrayList.ensureCapacity(length); for (int i = 0; i < length; i += 1) { this.put(JSONObject.wrap(Array.get(array, i))); } @@ -495,7 +498,7 @@ public int length() { * Get the optional object value associated with an index. * * @param index - * The index must be between 0 and length() - 1. + * The index must be between 0 and length() - 1. If not, null is returned. * @return An object value, or null if there is no object at that index. */ public Object opt(int index) { @@ -1150,7 +1153,13 @@ public JSONArray put(int index, Object value) throws JSONException { } if (index < this.length()) { this.myArrayList.set(index, value); + } else if(index == this.length()){ + // simple append + this.put(value); } else { + // if we are inserting past the length, we want to grow the array all at once + // instead of incrementally. + this.myArrayList.ensureCapacity(index + 1); while (index != this.length()) { this.put(JSONObject.NULL); } @@ -1302,7 +1311,7 @@ public JSONObject toJSONObject(JSONArray names) throws JSONException { if (names == null || names.length() == 0 || this.length() == 0) { return null; } - JSONObject jo = new JSONObject(); + JSONObject jo = new JSONObject(names.length()); for (int i = 0; i < names.length(); i += 1) { jo.put(names.getString(i), this.opt(i)); } diff --git a/JSONObject.java b/JSONObject.java index ff4acfab..65802519 100644 --- a/JSONObject.java +++ b/JSONObject.java @@ -178,7 +178,7 @@ public JSONObject() { * An array of strings. */ public JSONObject(JSONObject jo, String[] names) { - this(); + this(names.length); for (int i = 0; i < names.length; i += 1) { try { this.putOnce(names[i], jo.opt(names[i])); @@ -250,8 +250,10 @@ public JSONObject(JSONTokener x) throws JSONException { * the JSONObject. */ public JSONObject(Map m) { - this.map = new HashMap(); - if (m != null) { + if (m == null) { + this.map = new HashMap(); + } else { + this.map = new HashMap(m.size()); for (final Entry e : m.entrySet()) { final Object value = e.getValue(); if (value != null) { @@ -302,7 +304,7 @@ public JSONObject(Object bean) { * from the object. */ public JSONObject(Object object, String names[]) { - this(); + this(names.length); Class c = object.getClass(); for (int i = 0; i < names.length; i += 1) { String name = names[i]; @@ -371,6 +373,17 @@ public JSONObject(String baseName, Locale locale) throws JSONException { } } } + + /** + * Constructor to specify an initial capacity of the internal map. Useful for library + * internal calls where we know, or at least can best guess, how big this JSONObject + * will be. + * + * @param initialCapacity initial capacity of the internal map. + */ + protected JSONObject(int initialCapacity){ + this.map = new HashMap(initialCapacity); + } /** * Accumulate values under a key. It is similar to the put method except diff --git a/Property.java b/Property.java index 4f1d7c43..51b97ed5 100644 --- a/Property.java +++ b/Property.java @@ -41,7 +41,7 @@ of this software and associated documentation files (the "Software"), to deal * @throws JSONException */ public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException { - JSONObject jo = new JSONObject(); + JSONObject jo = new JSONObject(properties == null ? 0 : properties.size()); if (properties != null && !properties.isEmpty()) { Enumeration enumProperties = properties.propertyNames(); while(enumProperties.hasMoreElements()) {