[
https://issues.apache.org/jira/browse/COLLECTIONS-803?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17706159#comment-17706159
]
Alex Herbert commented on COLLECTIONS-803:
------------------------------------------
A cast to (K) may throw a cast exception as convertKey can return a plain
Object in convertKey (which is the mask object AbstractHashedMap.NULL). So it
is not possible to override the existing API with the converted key. Thanks for
identifying this as I had not tried out that idea.
I think this can be solved using a cache of the converted key, e.g.
{code:java}
private Object[] convertedKey = new Object[2];
// ...
@Override
protected Object convertKey(final Object key) {
if (key != null) {
// Copy locally
final Object[] pair = convertedKey;
if (pair[0] == key) {
return pair[1];
}
final char[] chars = key.toString().toCharArray();
for (int i = chars.length - 1; i >= 0; i--) {
chars[i] =
Character.toLowerCase(Character.toUpperCase(chars[i]));
}
String converted = new String(chars);
// Save for next conversion
convertedKey = new Object[] {key, converted};
return converted;
}
return AbstractHashedMap.NULL;
}
{code}
The map is not thread safe. So there is no requirement here for an atomic
reference. If there is any sort of memory issue where the convertedKey does not
match as expected (inside the createEntry method which converts the key again)
then the method will simply compute it again. Overhead over the existing
implementation is a single brach where the key may match and the converted form
is returned immediately. The rest is just simple housekeeping.
I've not tested this. It will require some checking that the custom
serialization methods function correctly. Adding a new private field changes
the serialization compatibility. The key point is that deserialization of a
serialized form saved with a prior version should end up with a non-null
convertedKey array. It doesn't matter what the array contains, just that it is
not null, and length at least 1, or else a NPE or IOOBE will occur on the first
put operation.
> CaseInsensitiveMap prevent duplicate key conversion on put
> ----------------------------------------------------------
>
> Key: COLLECTIONS-803
> URL: https://issues.apache.org/jira/browse/COLLECTIONS-803
> Project: Commons Collections
> Issue Type: Improvement
> Components: Map
> Affects Versions: 4.4
> Reporter: Simulant
> Priority: Minor
> Labels: performance
> Time Spent: 1h 50m
> Remaining Estimate: 0h
>
> When adding a new item into a {{CaseInsensitiveMap}} the {{convertKey(key)}}
> method is called twice, once in the {{put(key, value)}} method and second in
> the {{createEntry(next, hashCode, key, value)}} method. The result could be
> re-used resulting in a better performance.
> Depending on the {{toString()}} implementation of the key and the resulting
> length of the key before the lower case conversion the operation can get
> expensive and should not be called twice, as the {{CaseInsensitiveMap}}
> overwrites the {{convertKey(key)}} method and makes it more expensive and
> depending on the input unlike in the implementation of the
> {{AbstractHashedMap}}.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)