From 7b7535714d465cedeccbb23a3e0b5447d39eeab4 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Mon, 28 Sep 2020 18:28:58 +0200 Subject: [PATCH] IDEA-251640 avoid dependency on trove in our concurrent weak/soft map (part 1) GitOrigin-RevId: 4d0a086b3fd1a1fcdb6fcd432166bdecedeab09d --- .../psi/impl/search/HighlightingCaches.java | 32 +---- .../psi/impl/source/resolve/ResolveCache.java | 8 +- .../platform-resources/src/brokenPlugins.txt | 4 +- .../ContainerUtilCollectionsTest.java | 22 ++-- .../com/intellij/openapi/util/ObjectTree.java | 3 +- .../util/containers/CollectionFactory.java | 58 ++++++++- .../util/containers/ConcurrentRefHashMap.java | 36 +++--- .../containers/ConcurrentSoftHashMap.java | 15 +-- .../ConcurrentSoftKeySoftValueHashMap.java | 32 ++--- .../ConcurrentSoftValueHashMap.java | 3 +- .../containers/ConcurrentWeakHashMap.java | 21 ++-- .../ConcurrentWeakKeySoftValueHashMap.java | 29 +++-- .../ConcurrentWeakKeyWeakValueHashMap.java | 6 +- .../util/containers/ContainerUtil.java | 119 +++++++----------- .../util/containers/HashingStrategy.java | 52 ++++++++ .../intellij/util/containers/RefHashMap.java | 18 +-- .../util/containers/RefValueHashMap.java | 11 +- .../util/containers/SoftArrayHashMap.java | 44 +++---- .../intellij/util/containers/SoftHashMap.java | 15 +-- .../util/containers/SoftValueHashMap.java | 22 +--- .../intellij/util/containers/WeakHashMap.java | 17 ++- .../util/containers/WeakInterner.java | 3 +- .../util/containers/WeakValueHashMap.java | 7 -- 23 files changed, 284 insertions(+), 293 deletions(-) create mode 100644 platform/util/src/com/intellij/util/containers/HashingStrategy.java diff --git a/java/java-indexing-impl/src/com/intellij/psi/impl/search/HighlightingCaches.java b/java/java-indexing-impl/src/com/intellij/psi/impl/search/HighlightingCaches.java index 2179605a0aab..5ae9fe0f61c8 100644 --- a/java/java-indexing-impl/src/com/intellij/psi/impl/search/HighlightingCaches.java +++ b/java/java-indexing-impl/src/com/intellij/psi/impl/search/HighlightingCaches.java @@ -1,26 +1,12 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.psi.impl.search; -import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; import com.intellij.psi.impl.AnyPsiChangeListener; import com.intellij.psi.impl.PsiManagerImpl; +import com.intellij.util.containers.CollectionFactory; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -28,9 +14,9 @@ import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentMap; -class HighlightingCaches { +final class HighlightingCaches { public static HighlightingCaches getInstance(Project project) { - return ServiceManager.getService(project, HighlightingCaches.class); + return project.getService(HighlightingCaches.class); } private final List> allCaches = ContainerUtil.createConcurrentList(); @@ -43,11 +29,6 @@ class HighlightingCaches { allCaches.forEach(Map::clear); } } - - @Override - public void afterPsiChanged(boolean isPhysical) { - - } }); } @@ -60,9 +41,8 @@ class HighlightingCaches { // baseMethod -> all overriding methods final Map> OVERRIDING_METHODS = createWeakCache(); - @NotNull - private ConcurrentMap createWeakCache() { - ConcurrentMap map = ContainerUtil.createConcurrentWeakKeySoftValueMap(10, 0.7f, Runtime.getRuntime().availableProcessors(), ContainerUtil.canonicalStrategy()); + private @NotNull ConcurrentMap createWeakCache() { + ConcurrentMap map = CollectionFactory.createConcurrentWeakKeySoftValueMap(10, 0.7f, Runtime.getRuntime().availableProcessors()); allCaches.add(map); return map; } diff --git a/platform/core-impl/src/com/intellij/psi/impl/source/resolve/ResolveCache.java b/platform/core-impl/src/com/intellij/psi/impl/source/resolve/ResolveCache.java index a217470809ff..32d098ec58cf 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/source/resolve/ResolveCache.java +++ b/platform/core-impl/src/com/intellij/psi/impl/source/resolve/ResolveCache.java @@ -13,7 +13,6 @@ import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.IdempotenceChecker; import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ConcurrentWeakKeySoftValueHashMap; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.messages.MessageBus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -36,11 +35,6 @@ public class ResolveCache implements Disposable { LowMemoryWatcher.register(() -> onLowMemory(), this); } - @Deprecated - public ResolveCache(@NotNull MessageBus bus) { - clearCacheOnPsiChange(bus); - } - private void clearCacheOnPsiChange(@NotNull MessageBus bus) { bus.connect().subscribe(PsiManagerImpl.ANY_PSI_CHANGE_TOPIC, new AnyPsiChangeListener() { @Override @@ -91,7 +85,7 @@ public class ResolveCache implements Disposable { @NotNull private static Map createWeakMap() { //noinspection deprecation - return new ConcurrentWeakKeySoftValueHashMap(100, 0.75f, Runtime.getRuntime().availableProcessors(), ContainerUtil.canonicalStrategy()){ + return new ConcurrentWeakKeySoftValueHashMap(100, 0.75f, Runtime.getRuntime().availableProcessors()) { @NotNull @Override protected ValueReference createValueReference(@NotNull V value, @NotNull ReferenceQueue queue) { diff --git a/platform/platform-resources/src/brokenPlugins.txt b/platform/platform-resources/src/brokenPlugins.txt index 70e169efe55f..3dde5c69d307 100644 --- a/platform/platform-resources/src/brokenPlugins.txt +++ b/platform/platform-resources/src/brokenPlugins.txt @@ -1303,4 +1303,6 @@ gw.gosu.ij 5.0.0 com.illuminatedcloud.intellij 1.8.5.7-idea19 1.8.5.5-idea19 edu.clemson.resolve.jetbrains 0.1.2a com.ritesh.intellij.plugin.reviewboard 0.1.4 0.1.3 v0.1.2 0.1.1 0.1.0 0.1.2-beta 0.1.1-beta 0.1.0-beta -org.jetbrains.visual.programming.ide 1.0-SNAPSHOT \ No newline at end of file +org.jetbrains.visual.programming.ide 1.0-SNAPSHOT +de.nordgedanken.auto_hotkey 0.2.0 +org.rust.lang 0.3.131.3366-202 0.3.131.3366-201 \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/util/containers/ContainerUtilCollectionsTest.java b/platform/platform-tests/testSrc/com/intellij/util/containers/ContainerUtilCollectionsTest.java index d9ac45a4554d..7d082e3f051b 100644 --- a/platform/platform-tests/testSrc/com/intellij/util/containers/ContainerUtilCollectionsTest.java +++ b/platform/platform-tests/testSrc/com/intellij/util/containers/ContainerUtilCollectionsTest.java @@ -28,9 +28,9 @@ public class ContainerUtilCollectionsTest extends Assert { private static final long TIMEOUT = 5 * 60 * 1000; // 5 minutes - private static final TObjectHashingStrategy IGNORE_CASE_WITH_CRAZY_HASH_STRATEGY = new TObjectHashingStrategy() { + private static final HashingStrategy IGNORE_CASE_WITH_CRAZY_HASH_STRATEGY = new HashingStrategy() { @Override - public int computeHashCode(String object) { + public int hashCode(String object) { return Character.toLowerCase(object.charAt(object.length() - 1)); } @@ -48,7 +48,7 @@ public class ContainerUtilCollectionsTest extends Assert { @Test(timeout = TIMEOUT) public void testConcurrentSoftMapTossedEvenWithIdentityStrategy() { - ConcurrentMap map = ContainerUtil.createConcurrentSoftMap(10, 0.5f, 8, ContainerUtil.identityStrategy()); + ConcurrentMap map = ContainerUtil.createConcurrentSoftMap(10, 0.5f, 8, HashingStrategy.identity()); checkKeyTossedEventually(map); } @@ -69,34 +69,34 @@ public class ContainerUtilCollectionsTest extends Assert { @Test(timeout = TIMEOUT) public void testConcurrentWeakKeyWeakValueTossedEvenWithIdentityStrategy() { - ConcurrentMap map = ContainerUtil.createConcurrentWeakKeyWeakValueMap(ContainerUtil.identityStrategy()); + ConcurrentMap map = CollectionFactory.createConcurrentWeakKeyWeakValueIdentityMap(); checkKeyTossedEventually(map); checkValueTossedEventually(map); } @Test(timeout = TIMEOUT) public void testConcurrentSoftKeySoftValueTossedEvenWithIdentityStrategy() { - ConcurrentMap map = ContainerUtil.createConcurrentSoftKeySoftValueMap(10, 0.5f, 8, ContainerUtil.identityStrategy()); + ConcurrentMap map = CollectionFactory.createConcurrentSoftKeySoftValueIdentityMap(10, 0.5f, 8); checkKeyTossedEventually(map); checkValueTossedEventually(map); } @Test(timeout = TIMEOUT) public void testConcurrentWeakKeySoftValueTossedEvenWithIdentityStrategy() { - ConcurrentMap map = ContainerUtil.createConcurrentWeakKeySoftValueMap(10, 0.5f, 8, ContainerUtil.identityStrategy()); + ConcurrentMap map = CollectionFactory.createConcurrentWeakKeySoftValueIdentityMap(10, 0.5f, 8); checkKeyTossedEventually(map); checkValueTossedEventually(map); } @Test(timeout = TIMEOUT) public void testWeakMapTossedEvenWithIdentityStrategy() { - Map map = ContainerUtil.createWeakMap(10,0.5f,ContainerUtil.identityStrategy()); + Map map = CollectionFactory.createWeakIdentityMap(10, 0.5f); checkKeyTossedEventually(map); } @Test(timeout = TIMEOUT) public void testSoftMapTossedEvenWithIdentityStrategy() { - Map map = ContainerUtil.createSoftMap(ContainerUtil.identityStrategy()); + Map map = CollectionFactory.createSoftIdentityMap(); checkKeyTossedEventually(map); } @@ -148,7 +148,7 @@ public class ContainerUtilCollectionsTest extends Assert { } @Test(timeout = TIMEOUT) public void testConcurrentSKSVMapDoesntRetainOldValueKeyAfterPutWithTheSameKeyButDifferentValue() { - checkMapDoesntLeakOldValueAfterPutWithTheSameKeyButDifferentValue(ContainerUtil.createConcurrentSoftKeySoftValueMap(1,1,1,ContainerUtil.canonicalStrategy())); + checkMapDoesntLeakOldValueAfterPutWithTheSameKeyButDifferentValue(CollectionFactory.createConcurrentSoftKeySoftValueMap(1, 1, 1)); } private void checkMapDoesntLeakOldValueAfterPutWithTheSameKeyButDifferentValue(Map map) { @@ -281,14 +281,14 @@ public class ContainerUtilCollectionsTest extends Assert { @Test(timeout = TIMEOUT) public void testWeakNativeHashCodeDoesNotGetCalledWhenCustomStrategyIsSpecified() { - Map map = ContainerUtil.createWeakMap(10,0.5f,ContainerUtil.identityStrategy()); + Map map = CollectionFactory.createWeakIdentityMap(10, 0.5f); checkHashCodeDoesntCalledFor(map); } @Test(timeout = TIMEOUT) public void testSoftNativeHashCodeDoesNotGetCalledWhenCustomStrategyIsSpecified() { - Map map = ContainerUtil.createSoftMap(ContainerUtil.identityStrategy()); + Map map = CollectionFactory.createSoftIdentityMap(); checkHashCodeDoesntCalledFor(map); } diff --git a/platform/util/src/com/intellij/openapi/util/ObjectTree.java b/platform/util/src/com/intellij/openapi/util/ObjectTree.java index 236f60dc6003..63ec01b8b996 100644 --- a/platform/util/src/com/intellij/openapi/util/ObjectTree.java +++ b/platform/util/src/com/intellij/openapi/util/ObjectTree.java @@ -7,6 +7,7 @@ import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.objectTree.ThrowableInterner; import com.intellij.util.IncorrectOperationException; import com.intellij.util.SmartList; +import com.intellij.util.containers.CollectionFactory; import com.intellij.util.containers.ContainerUtil; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; @@ -25,7 +26,7 @@ final class ObjectTree { // guarded by treeLock private final Map myObject2NodeMap = new Reference2ObjectOpenHashMap<>(); // Disposable -> trace or boolean marker (if trace unavailable) - private final Map myDisposedObjects = ContainerUtil.createWeakMap(100, 0.5f, ContainerUtil.identityStrategy()); // guarded by treeLock + private final Map myDisposedObjects = CollectionFactory.createWeakIdentityMap(100, 0.5f); // guarded by treeLock private final Object treeLock = new Object(); diff --git a/platform/util/src/com/intellij/util/containers/CollectionFactory.java b/platform/util/src/com/intellij/util/containers/CollectionFactory.java index ffb5cf97d079..3e25a1b04988 100644 --- a/platform/util/src/com/intellij/util/containers/CollectionFactory.java +++ b/platform/util/src/com/intellij/util/containers/CollectionFactory.java @@ -30,29 +30,56 @@ public final class CollectionFactory { @Contract(value = " -> new", pure = true) public static @NotNull ConcurrentMap createConcurrentWeakIdentityMap() { - return new ConcurrentWeakHashMap<>(ContainerUtil.identityStrategy()); + return new ConcurrentWeakHashMap<>(HashingStrategy.identity()); } @Contract(value = " -> new", pure = true) public static @NotNull Map createWeakMap() { - return ContainerUtil.createWeakMap(); + //noinspection deprecation + return new WeakHashMap<>(4, 0.8f, HashingStrategy.canonical()); + } + + @Contract(value = "_,_,_ -> new", pure = true) + public static @NotNull ConcurrentMap createConcurrentWeakKeySoftValueIdentityMap(int initialCapacity, + float loadFactor, + int concurrencyLevel) { + //noinspection deprecation + return new ConcurrentWeakKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.identity()); + } + + public static @NotNull Map createWeakIdentityMap(int initialCapacity, float loadFactor) { + //noinspection deprecation + return new WeakHashMap<>(initialCapacity, loadFactor, HashingStrategy.identity()); } @Contract(value = " -> new", pure = true) public static @NotNull ConcurrentMap createConcurrentWeakKeyWeakValueMap() { - return ContainerUtil.createConcurrentWeakKeyWeakValueMap(ContainerUtil.canonicalStrategy()); + return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical()); + } + + @Contract(value = " -> new", pure = true) + public static @NotNull ConcurrentMap createConcurrentWeakKeyWeakValueIdentityMap() { + return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.identity()); } @Contract(value = "_,_,_ -> new", pure = true) public static @NotNull ConcurrentMap createConcurrentWeakMap(int initialCapacity, float loadFactor, int concurrencyLevel) { - return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, ContainerUtil.canonicalStrategy()); + return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical()); } @Contract(value = " -> new", pure = true) public static @NotNull ConcurrentMap createConcurrentWeakKeySoftValueMap() { - return ContainerUtil.createConcurrentWeakKeySoftValueMap(); + return createConcurrentWeakKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors()); + } + + @Contract(value = "_,_,_,-> new", pure = true) + public static @NotNull ConcurrentMap createConcurrentWeakKeySoftValueMap(int initialCapacity, + float loadFactor, + int concurrencyLevel) { + //noinspection deprecation + return new ConcurrentWeakKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical()); } public static @NotNull Map createCharSequenceMap(boolean caseSensitive, int expectedSize, float loadFactor) { @@ -95,6 +122,20 @@ public final class CollectionFactory { return new Object2ObjectOpenCustomHashMap<>(FastUtilHashingStrategies.getCaseInsensitiveStringStrategy()); } + @Contract(value = "_,_,_ -> new", pure = true) + static @NotNull ConcurrentMap createConcurrentSoftKeySoftValueMap(int initialCapacity, + float loadFactor, + int concurrencyLevel) { + return new ConcurrentSoftKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical()); + } + + @Contract(value = "_,_,_ -> new", pure = true) + static @NotNull ConcurrentMap createConcurrentSoftKeySoftValueIdentityMap(int initialCapacity, + float loadFactor, + int concurrencyLevel) { + return new ConcurrentSoftKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.identity()); + } + public static @NotNull Set createFilePathSet() { if (SystemInfoRt.isFileSystemCaseSensitive) { return new HashSet<>(); @@ -128,7 +169,7 @@ public final class CollectionFactory { public static @NotNull Set createFilePathSet(String @NotNull[] paths, boolean isFileSystemCaseSensitive) { if (isFileSystemCaseSensitive) { - return ContainerUtil.set(paths); + return new HashSet<>(Arrays.asList(paths)); } return new ObjectOpenCustomHashSet<>(paths, FastUtilHashingStrategies.getCaseInsensitiveStringStrategy()); } @@ -275,6 +316,11 @@ public final class CollectionFactory { return new ConcurrentSoftHashMap<>(); } + public static @NotNull Map createSoftIdentityMap() { + //noinspection deprecation + return new SoftHashMap<>(HashingStrategy.identity()); + } + public static void trimMap(@NotNull Map map) { if (map instanceof Object2ObjectOpenHashMap) { ((Object2ObjectOpenHashMap)map).trim(); diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentRefHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentRefHashMap.java index deb205712520..5b6dc9b50116 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentRefHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentRefHashMap.java @@ -1,7 +1,6 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.containers; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,11 +14,10 @@ import java.util.concurrent.ConcurrentMap; * Null keys are allowed * Null values are NOT allowed */ -abstract class ConcurrentRefHashMap extends AbstractMap implements ConcurrentMap, TObjectHashingStrategy { +abstract class ConcurrentRefHashMap extends AbstractMap implements ConcurrentMap, HashingStrategy { final ReferenceQueue myReferenceQueue = new ReferenceQueue<>(); private final ConcurrentMap, V> myMap; // hashing strategy must be canonical, we compute corresponding hash codes using our own myHashingStrategy - @NotNull - private final TObjectHashingStrategy myHashingStrategy; + private final @NotNull HashingStrategy myHashingStrategy; @FunctionalInterface interface KeyReference { @@ -33,8 +31,7 @@ abstract class ConcurrentRefHashMap extends AbstractMap implements C int hashCode(); } - @NotNull - abstract KeyReference createKeyReference(@NotNull K key, @NotNull TObjectHashingStrategy hashingStrategy); + abstract @NotNull KeyReference createKeyReference(@NotNull K key, @NotNull HashingStrategy hashingStrategy); private static final HardKey NULL_KEY = new HardKey() { @Override @@ -79,9 +76,9 @@ abstract class ConcurrentRefHashMap extends AbstractMap implements C this(initialCapacity, LOAD_FACTOR); } - private static final TObjectHashingStrategy THIS = new TObjectHashingStrategy() { + private static final HashingStrategy THIS = new HashingStrategy() { @Override - public int computeHashCode(Object object) { + public int hashCode(Object object) { throw new UnsupportedOperationException(); } @@ -90,20 +87,21 @@ abstract class ConcurrentRefHashMap extends AbstractMap implements C throw new UnsupportedOperationException(); } }; + private ConcurrentRefHashMap(int initialCapacity, float loadFactor) { //noinspection unchecked - this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL, (TObjectHashingStrategy)THIS); + this(initialCapacity, loadFactor, DEFAULT_CONCURRENCY_LEVEL, (HashingStrategy)THIS); } - ConcurrentRefHashMap(@NotNull final TObjectHashingStrategy hashingStrategy) { + ConcurrentRefHashMap(@NotNull HashingStrategy hashingStrategy) { this(DEFAULT_CAPACITY, LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL, hashingStrategy); } ConcurrentRefHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, - @NotNull TObjectHashingStrategy hashingStrategy) { - myHashingStrategy = hashingStrategy == THIS ? this : hashingStrategy; + @Nullable HashingStrategy hashingStrategy) { + myHashingStrategy = hashingStrategy == THIS ? this : (hashingStrategy == null ? HashingStrategy.canonical() : hashingStrategy); myMap = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel); } @@ -175,7 +173,7 @@ abstract class ConcurrentRefHashMap extends AbstractMap implements C K key = (K)o; //noinspection unchecked HardKey hardKey = (HardKey)HARD_KEY.get(); - hardKey.setKey(key, myHashingStrategy.computeHashCode(key)); + hardKey.setKey(key, myHashingStrategy.hashCode(key)); return hardKey; } @@ -216,7 +214,7 @@ abstract class ConcurrentRefHashMap extends AbstractMap implements C myMap.clear(); } - private static class RefEntry implements Map.Entry { + private static final class RefEntry implements Map.Entry { private final Map.Entry ent; private final K key; /* Strong reference to key, so that the GC will leave it alone as long as this Entry @@ -258,7 +256,7 @@ abstract class ConcurrentRefHashMap extends AbstractMap implements C } /* Internal class for entry sets */ - private class EntrySet extends AbstractSet> { + private final class EntrySet extends AbstractSet> { private final Set, V>> hashEntrySet = myMap.entrySet(); @NotNull @@ -388,8 +386,8 @@ abstract class ConcurrentRefHashMap extends AbstractMap implements C // MAKE SURE IT CONSISTENT WITH com.intellij.util.containers.ConcurrentHashMap @Override - public int computeHashCode(final K object) { - int h = object.hashCode(); + public int hashCode(@Nullable K object) { + int h = object == null ? 0 : object.hashCode(); h += ~(h << 9); h ^= h >>> 14; h += h << 4; @@ -398,7 +396,7 @@ abstract class ConcurrentRefHashMap extends AbstractMap implements C } @Override - public boolean equals(final K o1, final K o2) { - return o1.equals(o2); + public boolean equals(K o1, K o2) { + return Objects.equals(o1, o2); } } diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentSoftHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentSoftHashMap.java index 37984d741acd..c0d87e585c37 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentSoftHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentSoftHashMap.java @@ -1,8 +1,6 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - package com.intellij.util.containers; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import java.lang.ref.ReferenceQueue; @@ -21,17 +19,17 @@ final class ConcurrentSoftHashMap extends ConcurrentRefHashMap { ConcurrentSoftHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, - @NotNull TObjectHashingStrategy hashingStrategy) { + @NotNull HashingStrategy hashingStrategy) { super(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); } private static final class SoftKey extends SoftReference implements KeyReference { private final int myHash; // Hashcode of key, stored here since the key may be tossed by the GC - private final TObjectHashingStrategy myStrategy; + private final HashingStrategy myStrategy; private SoftKey(@NotNull K k, final int hash, - @NotNull TObjectHashingStrategy strategy, + @NotNull HashingStrategy strategy, @NotNull ReferenceQueue q) { super(k, q); myStrategy = strategy; @@ -55,10 +53,9 @@ final class ConcurrentSoftHashMap extends ConcurrentRefHashMap { } } - @NotNull @Override - protected KeyReference createKeyReference(@NotNull K key, - @NotNull TObjectHashingStrategy hashingStrategy) { - return new SoftKey<>(key, hashingStrategy.computeHashCode(key), hashingStrategy, myReferenceQueue); + protected @NotNull KeyReference createKeyReference(@NotNull K key, + @NotNull HashingStrategy hashingStrategy) { + return new SoftKey<>(key, hashingStrategy.hashCode(key), hashingStrategy, myReferenceQueue); } } diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentSoftKeySoftValueHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentSoftKeySoftValueHashMap.java index 2416bfb28108..d3b59f9dcbc9 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentSoftKeySoftValueHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentSoftKeySoftValueHashMap.java @@ -1,23 +1,7 @@ -/* - * Copyright 2000-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.containers; import com.intellij.util.ObjectUtils; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import java.lang.ref.ReferenceQueue; @@ -27,28 +11,28 @@ import java.lang.ref.SoftReference; * Concurrent map with soft keys and soft values. * Null keys are NOT allowed * Null values are NOT allowed - * To instantiate use {@link ContainerUtil#createConcurrentSoftKeySoftValueMap(int, float, int, TObjectHashingStrategy)} + * To instantiate use {@link ContainerUtil#createConcurrentSoftKeySoftValueMap(int, float, int, HashingStrategy)} */ -class ConcurrentSoftKeySoftValueHashMap extends ConcurrentWeakKeySoftValueHashMap { +final class ConcurrentSoftKeySoftValueHashMap extends ConcurrentWeakKeySoftValueHashMap { ConcurrentSoftKeySoftValueHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, - @NotNull final TObjectHashingStrategy hashingStrategy) { + @NotNull HashingStrategy hashingStrategy) { super(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); } private static class SoftKey extends SoftReference implements KeyReference { private final int myHash; // Hash code of the key, stored here since the key may be tossed by the GC - private final TObjectHashingStrategy myStrategy; + private final HashingStrategy myStrategy; @NotNull private final ValueReference myValueReference; SoftKey(@NotNull K k, @NotNull ValueReference valueReference, - @NotNull TObjectHashingStrategy strategy, + @NotNull HashingStrategy strategy, @NotNull ReferenceQueue queue) { super(k, queue); myValueReference = valueReference; - myHash = strategy.computeHashCode(k); + myHash = strategy.hashCode(k); myStrategy = strategy; } @@ -78,7 +62,7 @@ class ConcurrentSoftKeySoftValueHashMap extends ConcurrentWeakKeySoftValue @NotNull KeyReference createKeyReference(@NotNull K k, @NotNull final V v) { final ValueReference valueReference = createValueReference(v, myValueQueue); - SoftKey keyReference = new SoftKey<>(k, valueReference, myHashingStrategy, myKeyQueue); + KeyReference keyReference = new SoftKey<>(k, valueReference, myHashingStrategy, myKeyQueue); if (valueReference instanceof SoftValue) { ((SoftValue)valueReference).myKeyReference = keyReference; } diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentSoftValueHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentSoftValueHashMap.java index d0106031af3d..f9d1027cb88a 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentSoftValueHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentSoftValueHashMap.java @@ -1,5 +1,4 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - package com.intellij.util.containers; import org.jetbrains.annotations.NotNull; @@ -11,7 +10,7 @@ import java.lang.ref.SoftReference; * Concurrent strong key:K -> soft value:V map * Null keys are NOT allowed * Null values are NOT allowed - * Use {@link ContainerUtil#createConcurrentSoftValueMap()} to create this + * Use {@link CollectionFactory#createConcurrentSoftValueMap()} to create this */ final class ConcurrentSoftValueHashMap extends ConcurrentRefValueHashMap { private static final class MySoftReference extends SoftReference implements ValueReference { diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentWeakHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentWeakHashMap.java index ec6acbc7cf72..65b7c277e592 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentWeakHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentWeakHashMap.java @@ -1,7 +1,6 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.containers; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import java.lang.ref.ReferenceQueue; @@ -15,11 +14,11 @@ import java.lang.ref.WeakReference; final class ConcurrentWeakHashMap extends ConcurrentRefHashMap { private static final class WeakKey extends WeakReference implements KeyReference { private final int myHash; /* Hashcode of key, stored here since the key may be tossed by the GC */ - @NotNull private final TObjectHashingStrategy myStrategy; + @NotNull private final HashingStrategy myStrategy; private WeakKey(@NotNull K k, - final int hash, - @NotNull TObjectHashingStrategy strategy, + int hash, + @NotNull HashingStrategy strategy, @NotNull ReferenceQueue q) { super(k, q); myStrategy = strategy; @@ -43,26 +42,24 @@ final class ConcurrentWeakHashMap extends ConcurrentRefHashMap { } } - @NotNull @Override - protected KeyReference createKeyReference(@NotNull K key, - @NotNull TObjectHashingStrategy hashingStrategy) { - return new WeakKey<>(key, hashingStrategy.computeHashCode(key), hashingStrategy, myReferenceQueue); + protected @NotNull KeyReference createKeyReference(@NotNull K key, + @NotNull HashingStrategy hashingStrategy) { + return new WeakKey<>(key, hashingStrategy.hashCode(key), hashingStrategy, myReferenceQueue); } ConcurrentWeakHashMap(float loadFactor) { - //noinspection unchecked - super(DEFAULT_CAPACITY, loadFactor, DEFAULT_CONCURRENCY_LEVEL, TObjectHashingStrategy.CANONICAL); + super(DEFAULT_CAPACITY, loadFactor, DEFAULT_CONCURRENCY_LEVEL, HashingStrategy.canonical()); } ConcurrentWeakHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, - @NotNull TObjectHashingStrategy hashingStrategy) { + @NotNull HashingStrategy hashingStrategy) { super(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); } - ConcurrentWeakHashMap(@NotNull TObjectHashingStrategy hashingStrategy) { + ConcurrentWeakHashMap(@NotNull HashingStrategy hashingStrategy) { super(hashingStrategy); } } diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentWeakKeySoftValueHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentWeakKeySoftValueHashMap.java index 8c07b97c365a..913e60748a31 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentWeakKeySoftValueHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentWeakKeySoftValueHashMap.java @@ -1,37 +1,42 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - package com.intellij.util.containers; import com.intellij.openapi.util.Getter; import com.intellij.util.ObjectUtils; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** * Concurrent map with weak keys and soft values. * Null keys are NOT allowed * Null values are NOT allowed - * @deprecated Use {@link ContainerUtil#createConcurrentWeakKeySoftValueMap(int, float, int, TObjectHashingStrategy)} instead + * @deprecated Use {@link ContainerUtil#createConcurrentWeakKeySoftValueMap(int, float, int, HashingStrategy)} instead */ @Deprecated public class ConcurrentWeakKeySoftValueHashMap implements ConcurrentMap { private final ConcurrentMap, ValueReference> myMap; final ReferenceQueue myKeyQueue = new ReferenceQueue<>(); final ReferenceQueue myValueQueue = new ReferenceQueue<>(); - @NotNull final TObjectHashingStrategy myHashingStrategy; + @NotNull final HashingStrategy myHashingStrategy; + + protected ConcurrentWeakKeySoftValueHashMap(int initialCapacity, + float loadFactor, + int concurrencyLevel) { + this(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical()); + } protected ConcurrentWeakKeySoftValueHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, - @NotNull final TObjectHashingStrategy hashingStrategy) { + @NotNull HashingStrategy hashingStrategy) { myHashingStrategy = hashingStrategy; - myMap = ContainerUtil.newConcurrentMap(initialCapacity, loadFactor, concurrencyLevel); + myMap = new ConcurrentHashMap<>(initialCapacity, loadFactor, concurrencyLevel); } public interface KeyReference extends Getter { @@ -57,18 +62,18 @@ public class ConcurrentWeakKeySoftValueHashMap implements ConcurrentMap extends WeakReference implements KeyReference { + static final class WeakKey extends WeakReference implements KeyReference { private final int myHash; // Hash code of the key, stored here since the key may be tossed by the GC - private final TObjectHashingStrategy myStrategy; + private final HashingStrategy myStrategy; @NotNull private final ValueReference myValueReference; WeakKey(@NotNull K k, @NotNull ValueReference valueReference, - @NotNull TObjectHashingStrategy strategy, + @NotNull HashingStrategy strategy, @NotNull ReferenceQueue queue) { super(k, queue); myValueReference = valueReference; - myHash = strategy.computeHashCode(k); + myHash = strategy.hashCode(k); myStrategy = strategy; } @@ -124,7 +129,7 @@ public class ConcurrentWeakKeySoftValueHashMap implements ConcurrentMap createKeyReference(@NotNull K k, @NotNull final V v) { final ValueReference valueReference = createValueReference(v, myValueQueue); - WeakKey keyReference = new WeakKey<>(k, valueReference, myHashingStrategy, myKeyQueue); + KeyReference keyReference = new WeakKey<>(k, valueReference, myHashingStrategy, myKeyQueue); if (valueReference instanceof SoftValue) { ((SoftValue)valueReference).myKeyReference = keyReference; } @@ -197,7 +202,7 @@ public class ConcurrentWeakKeySoftValueHashMap implements ConcurrentMap hardKey = (HardKey)HARD_KEY.get(); - hardKey.set(key, myHashingStrategy.computeHashCode(key)); + hardKey.set(key, myHashingStrategy.hashCode(key)); return hardKey; } diff --git a/platform/util/src/com/intellij/util/containers/ConcurrentWeakKeyWeakValueHashMap.java b/platform/util/src/com/intellij/util/containers/ConcurrentWeakKeyWeakValueHashMap.java index fe12b94c2c82..4f43339406ed 100644 --- a/platform/util/src/com/intellij/util/containers/ConcurrentWeakKeyWeakValueHashMap.java +++ b/platform/util/src/com/intellij/util/containers/ConcurrentWeakKeyWeakValueHashMap.java @@ -1,9 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. - package com.intellij.util.containers; import com.intellij.util.ObjectUtils; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import java.lang.ref.ReferenceQueue; @@ -15,11 +13,11 @@ import java.lang.ref.WeakReference; * Null values are NOT allowed * Use {@link ContainerUtil#createConcurrentWeakKeyWeakValueMap()} to create this */ -class ConcurrentWeakKeyWeakValueHashMap extends ConcurrentWeakKeySoftValueHashMap { +final class ConcurrentWeakKeyWeakValueHashMap extends ConcurrentWeakKeySoftValueHashMap { ConcurrentWeakKeyWeakValueHashMap(int initialCapacity, float loadFactor, int concurrencyLevel, - @NotNull final TObjectHashingStrategy hashingStrategy) { + @NotNull final HashingStrategy hashingStrategy) { super(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); } diff --git a/platform/util/src/com/intellij/util/containers/ContainerUtil.java b/platform/util/src/com/intellij/util/containers/ContainerUtil.java index 75b07ed541b2..aa81cd755c75 100644 --- a/platform/util/src/com/intellij/util/containers/ContainerUtil.java +++ b/platform/util/src/com/intellij/util/containers/ContainerUtil.java @@ -411,15 +411,6 @@ public class ContainerUtil { return new THashSet<>(Arrays.asList(elements), strategy); } - /** - * @deprecated Use {@link HashSet}. - */ - @Contract(pure = true) - @Deprecated - public static @NotNull THashSet newTroveSet(@NotNull TObjectHashingStrategy strategy, @NotNull Collection elements) { - return new THashSet<>(elements, strategy); - } - /** * @deprecated Use {@link THashSet#THashSet(Collection)} */ @@ -429,24 +420,6 @@ public class ContainerUtil { return new THashSet<>(elements); } - /** - * @deprecated Use {@link it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet}. - */ - @Deprecated - @Contract(pure = true) - public static @NotNull THashSet newIdentityTroveSet() { - return new THashSet<>(identityStrategy()); - } - - /** - * @deprecated Use {@link it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet}. - */ - @Deprecated - @Contract(pure = true) - public static @NotNull THashSet newIdentityTroveSet(@NotNull Collection collection) { - return new THashSet<>(collection, identityStrategy()); - } - /** * @deprecated Use {@link it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap} */ @@ -2351,15 +2324,6 @@ public class ContainerUtil { } } - - /** - * @return read-only set consisting of the only element o - */ - @Contract(pure = true) - public static @NotNull Set singleton(final T o, final @NotNull TObjectHashingStrategy strategy) { - return strategy == canonicalStrategy() ? new SingletonSet<>(o) : SingletonSet.withCustomStrategy(o, strategy); - } - /** * @return read-only list consisting of the elements from all of the collections */ @@ -2660,41 +2624,34 @@ public class ContainerUtil { } @Contract(value = "_,_,_,_ -> new", pure = true) - public static @NotNull ConcurrentMap createConcurrentWeakKeySoftValueMap(int initialCapacity, - float loadFactor, - int concurrencyLevel, - final @NotNull TObjectHashingStrategy hashingStrategy) { + static @NotNull ConcurrentMap createConcurrentWeakKeySoftValueMap(int initialCapacity, + float loadFactor, + int concurrencyLevel, + final @NotNull HashingStrategy hashingStrategy) { //noinspection deprecation return new ConcurrentWeakKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); } @Contract(value = " -> new", pure = true) - public static @NotNull ConcurrentMap createConcurrentSoftKeySoftValueMap() { - return createConcurrentSoftKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors(), canonicalStrategy()); - } - - @Contract(value = "_,_,_,_ -> new", pure = true) - public static @NotNull ConcurrentMap createConcurrentSoftKeySoftValueMap(int initialCapacity, - float loadFactor, - int concurrencyLevel, - final @NotNull TObjectHashingStrategy hashingStrategy) { - return new ConcurrentSoftKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); + public static @NotNull ConcurrentMap createConcurrentSoftKeySoftValueMap() { + return new ConcurrentSoftKeySoftValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical()); } @Contract(value = " -> new", pure = true) public static @NotNull ConcurrentMap createConcurrentWeakKeySoftValueMap() { - return createConcurrentWeakKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors(), canonicalStrategy()); + //noinspection deprecation + return new ConcurrentWeakKeySoftValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical()); } @Contract(value = " -> new", pure = true) public static @NotNull ConcurrentMap createConcurrentWeakKeyWeakValueMap() { - return createConcurrentWeakKeyWeakValueMap(canonicalStrategy()); + return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical()); } + @ApiStatus.Internal @Contract(value = "_ -> new", pure = true) - public static @NotNull ConcurrentMap createConcurrentWeakKeyWeakValueMap(@NotNull TObjectHashingStrategy strategy) { - return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), - strategy); + public static @NotNull ConcurrentMap createConcurrentWeakKeyWeakValueMap(@NotNull HashingStrategy strategy) { + return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), strategy); } @Contract(value = " -> new", pure = true) @@ -2712,25 +2669,44 @@ public class ContainerUtil { return new ConcurrentWeakHashMap<>(0.75f); } + @ApiStatus.Internal @Contract(value = "_,_,_,_ -> new", pure = true) - public static @NotNull ConcurrentMap createConcurrentSoftMap(int initialCapacity, - float loadFactor, - int concurrencyLevel, - @NotNull TObjectHashingStrategy hashingStrategy) { + public static @NotNull ConcurrentMap createConcurrentSoftMap(int initialCapacity, + float loadFactor, + int concurrencyLevel, + @NotNull HashingStrategy hashingStrategy) { return new ConcurrentSoftHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); } - @Contract(value = "_,_,_,_ -> new", pure = true) - public static @NotNull ConcurrentMap createConcurrentWeakMap(int initialCapacity, - float loadFactor, - int concurrencyLevel, - @NotNull TObjectHashingStrategy hashingStrategy) { - return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy); + public static @NotNull HashingStrategy createHashingStrategy(@NotNull TObjectHashingStrategy hashingStrategy) { + return new HashingStrategy() { + @Override + public int hashCode(@Nullable K object) { + return hashingStrategy.computeHashCode(object); + } + + @Override + public boolean equals(@Nullable K o1, @Nullable K o2) { + return hashingStrategy.equals(o1, o2); + } + }; + } + + /** + * @deprecated Use {@link CollectionFactory#createConcurrentWeakMap(int, float, int)} + * or {@link CollectionFactory#createConcurrentWeakIdentityMap()} (int, float, int)}. + */ + @Deprecated + public static @NotNull ConcurrentMap createConcurrentWeakMap(int initialCapacity, + float loadFactor, + int concurrencyLevel, + @NotNull TObjectHashingStrategy hashingStrategy) { + return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, createHashingStrategy(hashingStrategy)); } @Contract(value = "_ -> new", pure = true) public static @NotNull ConcurrentMap createConcurrentWeakMap(@NotNull TObjectHashingStrategy hashingStrategy) { - return new ConcurrentWeakHashMap<>(hashingStrategy); + return new ConcurrentWeakHashMap<>(createHashingStrategy(hashingStrategy)); } /** @@ -3003,7 +2979,7 @@ public class ContainerUtil { */ @Contract(value = " -> new", pure = true) public static @NotNull Map createSoftValueMap() { - return new SoftValueHashMap<>(canonicalStrategy()); + return new SoftValueHashMap<>(); } /** @@ -3014,7 +2990,7 @@ public class ContainerUtil { @Contract(value = " -> new", pure = true) public static @NotNull Map createWeakValueMap() { //noinspection deprecation - return new WeakValueHashMap<>(canonicalStrategy()); + return new WeakValueHashMap<>(); } /** @@ -3029,7 +3005,7 @@ public class ContainerUtil { } @Contract(value = "_ -> new", pure = true) - public static @NotNull Map createSoftMap(@NotNull TObjectHashingStrategy strategy) { + static @NotNull Map createSoftMap(@NotNull HashingStrategy strategy) { //noinspection deprecation return new SoftHashMap<>(strategy); } @@ -3046,11 +3022,12 @@ public class ContainerUtil { @Contract(value = "_ -> new", pure = true) public static @NotNull Map createWeakMap(int initialCapacity) { - return createWeakMap(initialCapacity, 0.8f, canonicalStrategy()); + //noinspection deprecation + return new WeakHashMap<>(initialCapacity, 0.8f, HashingStrategy.canonical()); } @Contract(value = "_, _, _ -> new", pure = true) - public static @NotNull Map createWeakMap(int initialCapacity, float loadFactor, @NotNull TObjectHashingStrategy strategy) { + public static @NotNull Map createWeakMap(int initialCapacity, float loadFactor, @NotNull HashingStrategy strategy) { //noinspection deprecation return new WeakHashMap<>(initialCapacity, loadFactor, strategy); } diff --git a/platform/util/src/com/intellij/util/containers/HashingStrategy.java b/platform/util/src/com/intellij/util/containers/HashingStrategy.java new file mode 100644 index 000000000000..8da9637b8e1c --- /dev/null +++ b/platform/util/src/com/intellij/util/containers/HashingStrategy.java @@ -0,0 +1,52 @@ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.intellij.util.containers; + +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +@ApiStatus.Internal +public interface HashingStrategy { + int hashCode(@Nullable T object); + + boolean equals(@Nullable T o1, @Nullable T o2); + + static HashingStrategy canonical() { + //noinspection unchecked + return (HashingStrategy)CanonicalHashingStrategy.INSTANCE; + } + + static HashingStrategy identity() { + //noinspection unchecked + return (HashingStrategy)IdentityHashingStrategy.INSTANCE; + } +} + +final class CanonicalHashingStrategy implements HashingStrategy { + static final HashingStrategy INSTANCE = new CanonicalHashingStrategy<>(); + + @Override + public int hashCode(T value) { + return Objects.hashCode(value); + } + + @Override + public boolean equals(T o1, T o2) { + return Objects.equals(o1, o2); + } +} + +final class IdentityHashingStrategy implements HashingStrategy { + static final HashingStrategy INSTANCE = new IdentityHashingStrategy<>(); + + @Override + public int hashCode(T value) { + return System.identityHashCode(value); + } + + @Override + public boolean equals(T o1, T o2) { + return o1 == o2; + } +} diff --git a/platform/util/src/com/intellij/util/containers/RefHashMap.java b/platform/util/src/com/intellij/util/containers/RefHashMap.java index a1ec4ff13755..49c12a7f1331 100644 --- a/platform/util/src/com/intellij/util/containers/RefHashMap.java +++ b/platform/util/src/com/intellij/util/containers/RefHashMap.java @@ -18,17 +18,17 @@ abstract class RefHashMap extends AbstractMap implements Map { private final ReferenceQueue myReferenceQueue = new ReferenceQueue<>(); private final HardKey myHardKeyInstance = new HardKey(); // "singleton" @NotNull - private final TObjectHashingStrategy myStrategy; + private final HashingStrategy myStrategy; private Set> entrySet; private boolean processingQueue; - RefHashMap(int initialCapacity, float loadFactor, @NotNull final TObjectHashingStrategy strategy) { + RefHashMap(int initialCapacity, float loadFactor, @NotNull HashingStrategy strategy) { myStrategy = strategy; myMap = new MyMap(initialCapacity, loadFactor); } RefHashMap(int initialCapacity, float loadFactor) { - this(initialCapacity, loadFactor, ContainerUtil.canonicalStrategy()); + this(initialCapacity, loadFactor, HashingStrategy.canonical()); } RefHashMap(int initialCapacity) { @@ -44,11 +44,11 @@ abstract class RefHashMap extends AbstractMap implements Map { putAll(t); } - RefHashMap(@NotNull final TObjectHashingStrategy hashingStrategy) { + RefHashMap(@NotNull HashingStrategy hashingStrategy) { this(4, 0.8f, hashingStrategy); } - static boolean keyEqual(K k1, K k2, TObjectHashingStrategy strategy) { + static boolean keyEqual(K k1, K k2, HashingStrategy strategy) { return k1 == k2 || strategy.equals(k1, k2); } @@ -118,7 +118,7 @@ abstract class RefHashMap extends AbstractMap implements Map { } @NotNull - protected abstract Key createKey(@NotNull T k, @NotNull TObjectHashingStrategy strategy, @NotNull ReferenceQueue q); + protected abstract Key createKey(@NotNull T k, @NotNull HashingStrategy strategy, @NotNull ReferenceQueue q); private class HardKey implements Key { private K myObject; @@ -131,7 +131,7 @@ abstract class RefHashMap extends AbstractMap implements Map { private void set(@NotNull K object) { myObject = object; - myHash = myStrategy.computeHashCode(object); + myHash = myStrategy.hashCode(object); } private void clear() { @@ -257,9 +257,9 @@ abstract class RefHashMap extends AbstractMap implements Map { private final Entry ent; private final K key; // Strong reference to key, so that the GC will leave it alone as long as this Entry exists private final int myKeyHashCode; - @NotNull private final TObjectHashingStrategy myStrategy; + @NotNull private final HashingStrategy myStrategy; - private MyEntry(@NotNull Entry ent, @NotNull K key, int keyHashCode, @NotNull TObjectHashingStrategy strategy) { + private MyEntry(@NotNull Entry ent, @NotNull K key, int keyHashCode, @NotNull HashingStrategy strategy) { this.ent = ent; this.key = key; myKeyHashCode = keyHashCode; diff --git a/platform/util/src/com/intellij/util/containers/RefValueHashMap.java b/platform/util/src/com/intellij/util/containers/RefValueHashMap.java index 59772e8636db..6cedcb49c135 100644 --- a/platform/util/src/com/intellij/util/containers/RefValueHashMap.java +++ b/platform/util/src/com/intellij/util/containers/RefValueHashMap.java @@ -1,4 +1,4 @@ -// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.containers; import com.intellij.openapi.util.Getter; @@ -10,11 +10,12 @@ import org.jetbrains.annotations.Debug; import org.jetbrains.annotations.NotNull; import java.lang.ref.ReferenceQueue; +import java.util.HashMap; import java.util.*; @Debug.Renderer(text = "\"size = \" + size()", hasChildren = "!isEmpty()", childrenArray = "childrenArray()") -abstract class RefValueHashMap implements Map{ - private final Map> myMap; +abstract class RefValueHashMap implements Map { + private final Map> myMap; private final ReferenceQueue myQueue = new ReferenceQueue<>(); @NotNull @@ -33,7 +34,7 @@ abstract class RefValueHashMap implements Map{ } RefValueHashMap() { - myMap = new THashMap<>(); + myMap = new HashMap<>(); } RefValueHashMap(@NotNull TObjectHashingStrategy strategy) { @@ -94,7 +95,7 @@ abstract class RefValueHashMap implements Map{ @Override public boolean isEmpty() { - return myMap.isEmpty(); + return myMap.isEmpty(); } @Override diff --git a/platform/util/src/com/intellij/util/containers/SoftArrayHashMap.java b/platform/util/src/com/intellij/util/containers/SoftArrayHashMap.java index ab1513c0e46d..e2b0c52f10bc 100644 --- a/platform/util/src/com/intellij/util/containers/SoftArrayHashMap.java +++ b/platform/util/src/com/intellij/util/containers/SoftArrayHashMap.java @@ -1,40 +1,25 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.containers; -import com.intellij.util.PairProcessor; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import java.util.Map; +import java.util.function.BiPredicate; /** * @author peter */ -public class SoftArrayHashMap implements Cloneable { +public final class SoftArrayHashMap implements Cloneable { private Map> myContinuationMap; private Map myValuesMap; private V myEmptyValue; - private final TObjectHashingStrategy myStrategy; + private final HashingStrategy myStrategy; public SoftArrayHashMap() { - this(ContainerUtil.canonicalStrategy()); + this(HashingStrategy.canonical()); } - public SoftArrayHashMap(@NotNull TObjectHashingStrategy strategy) { + private SoftArrayHashMap(@NotNull HashingStrategy strategy) { myStrategy = strategy; } @@ -60,10 +45,12 @@ public class SoftArrayHashMap implements Cloneable { return get(key, 0); } - public boolean processLeafEntries(final PairProcessor processor) { + public boolean processLeafEntries(@NotNull BiPredicate processor) { if (myValuesMap != null) { for (T t : myValuesMap.keySet()) { - if (!processor.process(t, myValuesMap.get(t))) return false; + if (!processor.test(t, myValuesMap.get(t))) { + return false; + } } } if (myContinuationMap != null) { @@ -78,12 +65,14 @@ public class SoftArrayHashMap implements Cloneable { final T key = array[index]; if (index == array.length - 1) { if (myValuesMap == null) { - myValuesMap = ContainerUtil.createSoftMap(myStrategy); + //noinspection deprecation + myValuesMap = new SoftHashMap<>(myStrategy); } myValuesMap.put(key, value); } else { if (myContinuationMap == null) { - myContinuationMap = ContainerUtil.createSoftMap(myStrategy); + //noinspection deprecation + myContinuationMap = new SoftHashMap<>(myStrategy); } SoftArrayHashMap softArrayHashMap = myContinuationMap.get(key); if (softArrayHashMap == null) { @@ -121,8 +110,9 @@ public class SoftArrayHashMap implements Cloneable { } private Map copyMap(final Map map) { - final Map copy = ContainerUtil.createSoftMap(); - for (final Map.Entry entry : map.entrySet()) { + //noinspection deprecation + Map copy = new SoftHashMap<>(map.size()); + for (Map.Entry entry : map.entrySet()) { copy.put(entry.getKey(), entry.getValue()); } return copy; diff --git a/platform/util/src/com/intellij/util/containers/SoftHashMap.java b/platform/util/src/com/intellij/util/containers/SoftHashMap.java index d03eede99556..e19aef3ae00c 100644 --- a/platform/util/src/com/intellij/util/containers/SoftHashMap.java +++ b/platform/util/src/com/intellij/util/containers/SoftHashMap.java @@ -3,7 +3,6 @@ package com.intellij.util.containers; import com.intellij.reference.SoftReference; import com.intellij.util.DeprecatedMethodException; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -23,7 +22,7 @@ public final class SoftHashMap extends RefHashMap { * Null keys are NOT allowed * Null values are allowed * - * @deprecated use {@link ContainerUtil#createSoftMap()} instead + * @deprecated use {@link CollectionFactory#createSoftMap()} instead */ @Deprecated public SoftHashMap() { @@ -34,25 +33,23 @@ public final class SoftHashMap extends RefHashMap { super(initialCapacity); } - SoftHashMap(@NotNull TObjectHashingStrategy hashingStrategy) { + SoftHashMap(@NotNull HashingStrategy hashingStrategy) { super(hashingStrategy); } - - @NotNull @Override - protected Key createKey(@NotNull T k, @NotNull TObjectHashingStrategy strategy, @NotNull ReferenceQueue q) { + protected @NotNull Key createKey(@NotNull T k, @NotNull HashingStrategy strategy, @NotNull ReferenceQueue q) { return new SoftKey<>(k, strategy, q); } private static final class SoftKey extends SoftReference implements Key { private final int myHash; /* Hash code of key, stored here since the key may be tossed by the GC */ - @NotNull private final TObjectHashingStrategy myStrategy; + @NotNull private final HashingStrategy myStrategy; - private SoftKey(@NotNull T k, @NotNull TObjectHashingStrategy strategy, @NotNull ReferenceQueue q) { + private SoftKey(@NotNull T k, @NotNull HashingStrategy strategy, @NotNull ReferenceQueue q) { super(k, q); myStrategy = strategy; - myHash = strategy.computeHashCode(k); + myHash = strategy.hashCode(k); } @Override diff --git a/platform/util/src/com/intellij/util/containers/SoftValueHashMap.java b/platform/util/src/com/intellij/util/containers/SoftValueHashMap.java index 593576fc19e8..ed03c0730dee 100644 --- a/platform/util/src/com/intellij/util/containers/SoftValueHashMap.java +++ b/platform/util/src/com/intellij/util/containers/SoftValueHashMap.java @@ -1,22 +1,7 @@ -/* - * Copyright 2000-2009 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.containers; import com.intellij.reference.SoftReference; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import java.lang.ref.ReferenceQueue; @@ -40,11 +25,6 @@ final class SoftValueHashMap extends RefValueHashMap{ } } - - SoftValueHashMap(@NotNull TObjectHashingStrategy strategy) { - super(strategy); - } - @Override protected MyReference createReference(@NotNull K key, V value, @NotNull ReferenceQueue queue) { return new MySoftReference<>(key, value, queue); diff --git a/platform/util/src/com/intellij/util/containers/WeakHashMap.java b/platform/util/src/com/intellij/util/containers/WeakHashMap.java index c1a91fdc997e..0b7457a062ba 100644 --- a/platform/util/src/com/intellij/util/containers/WeakHashMap.java +++ b/platform/util/src/com/intellij/util/containers/WeakHashMap.java @@ -2,7 +2,6 @@ package com.intellij.util.containers; import com.intellij.util.DeprecatedMethodException; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -19,37 +18,37 @@ import java.lang.ref.WeakReference; * Do not use this class if you have null keys (shame on you). * Otherwise it's the same as java.util.WeakHashMap, you are free to use either. * - * @deprecated use {@link ContainerUtil#createWeakMap()} instead + * @deprecated use {@link CollectionFactory#createWeakMap()} instead */ @Deprecated public final class WeakHashMap extends RefHashMap { public WeakHashMap(int initialCapacity) { super(initialCapacity); - DeprecatedMethodException.report("Use ContainerUtil.createWeakMap() instead"); + DeprecatedMethodException.report("Use CollectionFactory.createWeakMap() instead"); } public WeakHashMap() { - DeprecatedMethodException.report("Use ContainerUtil.createWeakMap() instead"); + DeprecatedMethodException.report("Use CollectionFactory.createWeakMap() instead"); } - WeakHashMap(int initialCapacity, float loadFactor, @NotNull TObjectHashingStrategy strategy) { + WeakHashMap(int initialCapacity, float loadFactor, @NotNull HashingStrategy strategy) { super(initialCapacity, loadFactor, strategy); } @NotNull @Override - protected Key createKey(@NotNull T k, @NotNull TObjectHashingStrategy strategy, @NotNull ReferenceQueue q) { + protected Key createKey(@NotNull T k, @NotNull HashingStrategy strategy, @NotNull ReferenceQueue q) { return new WeakKey<>(k, strategy, q); } private static final class WeakKey extends WeakReference implements Key { private final int myHash; // Hashcode of key, stored here since the key may be tossed by the GC - @NotNull private final TObjectHashingStrategy myStrategy; + @NotNull private final HashingStrategy myStrategy; - private WeakKey(@NotNull T k, @NotNull TObjectHashingStrategy strategy, @NotNull ReferenceQueue q) { + private WeakKey(@NotNull T k, @NotNull HashingStrategy strategy, @NotNull ReferenceQueue q) { super(k, q); myStrategy = strategy; - myHash = strategy.computeHashCode(k); + myHash = strategy.hashCode(k); } @Override diff --git a/platform/util/src/com/intellij/util/containers/WeakInterner.java b/platform/util/src/com/intellij/util/containers/WeakInterner.java index a69693b43b54..6e5f15ee5199 100644 --- a/platform/util/src/com/intellij/util/containers/WeakInterner.java +++ b/platform/util/src/com/intellij/util/containers/WeakInterner.java @@ -27,7 +27,8 @@ public class WeakInterner extends Interner { } public WeakInterner(@NotNull TObjectHashingStrategy strategy) { - myMap = ContainerUtil.createConcurrentWeakKeyWeakValueMap(strategy); + myMap = new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), + ContainerUtil.createHashingStrategy(strategy)); } @Override diff --git a/platform/util/src/com/intellij/util/containers/WeakValueHashMap.java b/platform/util/src/com/intellij/util/containers/WeakValueHashMap.java index d4fb8021df8d..4e99d10feb30 100644 --- a/platform/util/src/com/intellij/util/containers/WeakValueHashMap.java +++ b/platform/util/src/com/intellij/util/containers/WeakValueHashMap.java @@ -1,8 +1,6 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.containers; -import com.intellij.util.DeprecatedMethodException; -import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import java.lang.ref.ReferenceQueue; @@ -33,11 +31,6 @@ public final class WeakValueHashMap extends RefValueHashMap { */ @Deprecated public WeakValueHashMap() { - DeprecatedMethodException.report("Use ContainerUtil#createWeakValueMap() instead"); - } - - WeakValueHashMap(@NotNull TObjectHashingStrategy strategy) { - super(strategy); } @Override