9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-25 18:09:17 +00:00

make StringCanonizingOpenHashMap faster

This commit is contained in:
Taiyou06
2025-04-13 03:23:40 +02:00
parent bb67247bbd
commit 2308f08ae3

View File

@@ -11,21 +11,31 @@ import java.util.function.Function;
public class StringCanonizingOpenHashMap<T> extends Object2ObjectOpenHashMap<String, T> {
private static final Interner<String> KEY_INTERNER = Interners.newWeakInterner();
private final float loadFactor;
private static String intern(String key) {
return key != null ? KEY_INTERNER.intern(key) : null;
if (key == null) return null;
String jvmInterned = key.intern();
if (jvmInterned == key) {
return key;
}
return KEY_INTERNER.intern(key);
}
public StringCanonizingOpenHashMap() {
super();
this.loadFactor = 0.8f;
}
public StringCanonizingOpenHashMap(int expectedSize) {
super(expectedSize);
this.loadFactor = 0.8f;
}
public StringCanonizingOpenHashMap(int expectedSize, float loadFactor) {
super(expectedSize, loadFactor);
this.loadFactor = loadFactor;
}
@Override
@@ -36,9 +46,16 @@ public class StringCanonizingOpenHashMap<T> extends Object2ObjectOpenHashMap<Str
@Override
public void putAll(Map<? extends String, ? extends T> m) {
if (m.isEmpty()) return;
Map<String, T> tmp = new Object2ObjectOpenHashMap<>(m.size());
m.forEach((k, v) -> tmp.put(intern(k), v));
super.putAll(tmp);
// Fast path for maps that already have interned keys
if (m instanceof StringCanonizingOpenHashMap) {
super.putAll(m);
return;
}
// Process each entry directly rather than creating a temporary map
for (Map.Entry<? extends String, ? extends T> entry : m.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
private void putWithoutInterning(String key, T value) {
@@ -46,11 +63,17 @@ public class StringCanonizingOpenHashMap<T> extends Object2ObjectOpenHashMap<Str
}
public static <T> StringCanonizingOpenHashMap<T> deepCopy(StringCanonizingOpenHashMap<T> incomingMap, Function<T, T> deepCopier) {
StringCanonizingOpenHashMap<T> newMap = new StringCanonizingOpenHashMap<>(incomingMap.size(), 0.8f);
int size = incomingMap.size();
if (size == 0) {
return new StringCanonizingOpenHashMap<>(0, incomingMap.loadFactor);
}
// Pre-allocate
StringCanonizingOpenHashMap<T> newMap = new StringCanonizingOpenHashMap<>(size, incomingMap.loadFactor);
ObjectIterator<Entry<String, T>> iterator = incomingMap.object2ObjectEntrySet().fastIterator();
while (iterator.hasNext()) {
Map.Entry<String, T> entry = iterator.next();
Entry<String, T> entry = iterator.next();
// Keys are already interned, so we can add them directly
newMap.putWithoutInterning(entry.getKey(), deepCopier.apply(entry.getValue()));
}