[core] move some maps to intellij.platform.util.collections

GitOrigin-RevId: 95bb9adb56b90436b707a55ec4960aed1a41f6c7
This commit is contained in:
Alexander Zolotov
2021-05-25 19:04:03 +02:00
committed by intellij-monorepo-bot
parent 4869532449
commit 60a3a3b416
19 changed files with 236 additions and 149 deletions

View File

@@ -8,6 +8,7 @@ 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 com.intellij.util.containers.HashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -42,7 +43,8 @@ final class HighlightingCaches {
final Map<PsiMethod, Iterable<PsiMethod>> OVERRIDING_METHODS = createWeakCache();
private @NotNull <T,V> ConcurrentMap<T,V> createWeakCache() {
ConcurrentMap<T, V> map = CollectionFactory.createConcurrentWeakKeySoftValueMap(10, 0.7f, Runtime.getRuntime().availableProcessors());
ConcurrentMap<T, V> map = CollectionFactory.createConcurrentWeakKeySoftValueMap(10, 0.7f, Runtime.getRuntime().availableProcessors(),
HashingStrategy.canonical());
allCaches.add(map);
return map;
}

View File

@@ -95,7 +95,7 @@ public class ContainerUtilCollectionsTest extends Assert {
@Test(timeout = TIMEOUT)
public void testSoftMapTossedEvenWithIdentityStrategy() {
Map<Object, Object> map = CollectionFactory.createSoftIdentityMap();
Map<Object, Object> map = ContainerUtil.createSoftMap(HashingStrategy.identity());
checkKeyTossedEventually(map);
}
@@ -266,7 +266,7 @@ public class ContainerUtilCollectionsTest extends Assert {
@Test(timeout = TIMEOUT)
public void testWeakMapCustomStrategy() {
Map<String, String> map = ContainerUtil.createWeakMap(10, 0.5f, IGNORE_CASE_WITH_CRAZY_HASH_STRATEGY);
Map<String, String> map = CollectionFactory.createWeakMap(10, 0.5f, IGNORE_CASE_WITH_CRAZY_HASH_STRATEGY);
String keyL = "ab";
String keyU = StringUtil.toUpperCase(keyL);
@@ -288,7 +288,7 @@ public class ContainerUtilCollectionsTest extends Assert {
@Test(timeout = TIMEOUT)
public void testSoftNativeHashCodeDoesNotGetCalledWhenCustomStrategyIsSpecified() {
Map<Object, Object> map = CollectionFactory.createSoftIdentityMap();
Map<Object, Object> map = ContainerUtil.createSoftMap(HashingStrategy.identity());
checkHashCodeDoesntCalledFor(map);
}

View File

@@ -1,16 +1,17 @@
// 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.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.openapi.diagnostic.LoggerRt;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public final class DeprecatedMethodException extends RuntimeException {
private static final Set<String> BEAT_DEAD_HORSE = ContainerUtil.newConcurrentSet();
private static final Logger LOG = Logger.getInstance(DeprecatedMethodException.class);
private static final Set<String> BEAT_DEAD_HORSE = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
private static final LoggerRt LOG = LoggerRt.getInstance(DeprecatedMethodException.class);
private DeprecatedMethodException(@NotNull String message) {
super(message);
}
@@ -20,7 +21,7 @@ public final class DeprecatedMethodException extends RuntimeException {
*/
public static void report(@NotNull @NonNls String message) {
if (!BEAT_DEAD_HORSE.add(message)) return;
Class<?> superClass = ReflectionUtil.findCallerClass(2);
Class<?> superClass = ReflectionUtilRt.findCallerClass(2);
@NonNls String superClassName = superClass != null ? superClass.getName() : "<no class>";
String text = "This method in '" + superClassName +
"' is deprecated and going to be removed soon. " + message;
@@ -32,7 +33,7 @@ public final class DeprecatedMethodException extends RuntimeException {
*/
public static void reportDefaultImplementation(@NotNull Class<?> thisClass, @NotNull String methodName, @NotNull String message) {
if (!BEAT_DEAD_HORSE.add(methodName + "###" + message + "###" + thisClass)) return;
Class<?> superClass = ReflectionUtil.findCallerClass(2);
Class<?> superClass = ReflectionUtilRt.findCallerClass(2);
@NonNls String superClassName = superClass != null ? superClass.getName() : "<no class>";
String text = "The default implementation of method '" + superClassName + "." + methodName + "' is deprecated, you need to override it in '" +
thisClass + "'. " + message;

View File

@@ -1,6 +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;
import com.intellij.openapi.diagnostic.LoggerRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -68,4 +69,32 @@ public final class ReflectionUtilRt {
return null;
}
private static final class MySecurityManager extends SecurityManager {
private static final MySecurityManager INSTANCE = new MySecurityManager();
Class<?>[] getStack() {
return getClassContext();
}
}
/**
* Returns the class this method was called 'framesToSkip' frames up the caller hierarchy.
*
* NOTE:
* <b>Extremely expensive!
* Please consider not using it.
* These aren't the droids you're looking for!</b>
*/
@Nullable
public static Class<?> findCallerClass(int framesToSkip) {
try {
Class<?>[] stack = MySecurityManager.INSTANCE.getStack();
int indexFromTop = 1 + framesToSkip;
return stack.length > indexFromTop ? stack[indexFromTop] : null;
}
catch (Exception e) {
LoggerRt.getInstance(ReflectionUtilRt.class).warn(e);
return null;
}
}
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2021 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-2021 JetBrains s.r.o. and contributors. 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.SystemInfoRt;
@@ -18,6 +18,11 @@ public final class CollectionFactory {
return new ConcurrentWeakHashMap<>(0.75f);
}
@Contract(value = "_, -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakMap(HashingStrategy<? super K> strategy) {
return new ConcurrentWeakHashMap<>(strategy);
}
@Contract(value = " -> new", pure = true)
public static @NotNull <V> ConcurrentMap<String, V> createConcurrentWeakCaseInsensitiveMap() {
return new ConcurrentWeakHashMap<>(HashingStrategy.caseInsensitive());
@@ -40,8 +45,13 @@ public final class CollectionFactory {
@Contract(value = " -> new", pure = true)
public static @NotNull <K, V> Map<K, V> createWeakMap() {
return createWeakMap(4, 0.8f, HashingStrategy.canonical());
}
@Contract(value = "_,_,_ -> new", pure = true)
public static @NotNull <K, V> Map<K, V> createWeakMap(int initialCapacity, float loadFactor, @NotNull HashingStrategy<? super K> hashingStrategy) {
//noinspection deprecation
return new WeakHashMap<>(4, 0.8f, HashingStrategy.canonical());
return new WeakHashMap<>(initialCapacity, loadFactor, hashingStrategy);
}
@Contract(value = "_,_,_ -> new", pure = true)
@@ -53,8 +63,7 @@ public final class CollectionFactory {
}
public static @NotNull <K, V> Map<K, V> createWeakIdentityMap(int initialCapacity, float loadFactor) {
//noinspection deprecation
return new WeakHashMap<>(initialCapacity, loadFactor, HashingStrategy.identity());
return createWeakMap(initialCapacity, loadFactor, HashingStrategy.identity());
}
@Contract(value = " -> new", pure = true)
@@ -62,29 +71,36 @@ public final class CollectionFactory {
return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical());
}
@Contract(value = "_ -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeyWeakValueMap(HashingStrategy<? super K> strategy) {
return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), strategy);
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeyWeakValueIdentityMap() {
return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.identity());
}
@Contract(value = "_,_,_ -> new", pure = true)
@Contract(value = "_,_,_,_ -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakMap(int initialCapacity,
float loadFactor,
int concurrencyLevel) {
return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical());
int concurrencyLevel,
HashingStrategy<? super K> hashingStrategy) {
return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeySoftValueMap() {
return createConcurrentWeakKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors());
return createConcurrentWeakKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical());
}
@Contract(value = "_,_,_,-> new", pure = true)
@Contract(value = "_,_,_,_-> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeySoftValueMap(int initialCapacity,
float loadFactor,
int concurrencyLevel) {
int concurrencyLevel,
@NotNull HashingStrategy<? super K> hashingStrategy) {
//noinspection deprecation
return new ConcurrentWeakKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical());
return new ConcurrentWeakKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
public static @NotNull <T> Map<CharSequence, T> createCharSequenceMap(boolean caseSensitive, int expectedSize, float loadFactor) {
@@ -137,9 +153,9 @@ public final class CollectionFactory {
@Contract(value = "_,_,_ -> new", pure = true)
@SuppressWarnings("SameParameterValue")
static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentSoftKeySoftValueMap(int initialCapacity,
float loadFactor,
int concurrencyLevel) {
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentSoftKeySoftValueMap(int initialCapacity,
float loadFactor,
int concurrencyLevel) {
return new ConcurrentSoftKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, HashingStrategy.canonical());
}
@@ -171,7 +187,7 @@ public final class CollectionFactory {
: new ObjectOpenCustomHashSet<>(paths, FastUtilHashingStrategies.getCaseInsensitiveStringStrategy());
}
public static @NotNull Set<String> createFilePathSet(String @NotNull[] paths, boolean isFileSystemCaseSensitive) {
public static @NotNull Set<String> createFilePathSet(String @NotNull [] paths, boolean isFileSystemCaseSensitive) {
//noinspection SSBasedInspection
return isFileSystemCaseSensitive
? new HashSet<>(Arrays.asList(paths))
@@ -261,7 +277,6 @@ public final class CollectionFactory {
*/
@Contract(value = "-> new", pure = true)
public static <K> @NotNull Set<K> createSmallMemoryFootprintLinkedSet() {
//noinspection SSBasedInspection
return new ObjectLinkedOpenHashSet<>();
}
@@ -291,13 +306,16 @@ public final class CollectionFactory {
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentSoftMap() {
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentSoftMap() {
return new ConcurrentSoftHashMap<>();
}
public static @NotNull <K, V> Map<K, V> createSoftIdentityMap() {
//noinspection deprecation
return new SoftHashMap<>(HashingStrategy.identity());
@Contract(value = "_,_,_,_-> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentSoftMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull HashingStrategy<? super K> hashingStrategy) {
return new ConcurrentSoftHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
public static void trimMap(@NotNull Map<?, ?> map) {

View File

@@ -1,8 +1,8 @@
// 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.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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.text.StringUtil;
import com.intellij.openapi.util.text.Strings;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
@@ -196,6 +196,6 @@ abstract class ConcurrentRefValueHashMap<K, V> implements ConcurrentMap<K, V> {
@Override
public String toString() {
return "map size:" + size() + " [" + StringUtil.join(entrySet(), ",") + "]";
return "map size:" + size() + " [" + Strings.join(entrySet(), ",") + "]";
}
}

View File

@@ -1,7 +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.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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 com.intellij.util.ObjectUtilsRt;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.ReferenceQueue;
@@ -67,7 +67,7 @@ final class ConcurrentSoftKeySoftValueHashMap<K, V> extends ConcurrentWeakKeySof
if (valueReference instanceof SoftValue) {
((SoftValue<K,V>)valueReference).myKeyReference = keyReference;
}
ObjectUtils.reachabilityFence(k);
ObjectUtilsRt.reachabilityFence(k);
return keyReference;
}
}

View File

@@ -1,9 +1,9 @@
// Copyright 2000-2021 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-2021 JetBrains s.r.o. and contributors. 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.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.util.text.StringUtilRt;
import com.intellij.openapi.util.text.Strings;
import it.unimi.dsi.fastutil.Hash;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
@@ -94,7 +94,7 @@ final class FastUtilCharSequenceHashingStrategy implements Hash.Strategy<CharSeq
if (o == null) {
return 0;
}
return isCaseSensitive ? StringUtil.stringHashCode(o) : StringUtil.stringHashCodeInsensitive(o);
return isCaseSensitive ? Strings.stringHashCode(o) : Strings.stringHashCodeInsensitive(o);
}
@Override

View File

@@ -1,7 +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.
// Copyright 2000-2021 JetBrains s.r.o. and contributors. 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 com.intellij.util.ObjectUtilsRt;
import it.unimi.dsi.fastutil.HashCommon;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import org.jetbrains.annotations.NotNull;
@@ -82,7 +82,7 @@ abstract class RefHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V> {
newKey[pos] = k;
newValue[pos] = value[i];
// avoid inserting gced keys into new table
ObjectUtils.reachabilityFence(referent);
ObjectUtilsRt.reachabilityFence(referent);
}
newValue[newN] = value[n];
n = newN;

View File

@@ -804,12 +804,7 @@ public class StringUtil extends StringUtilRt {
@Contract(pure = true)
public static int stringHashCode(@NotNull CharSequence chars) {
if (chars instanceof String || chars instanceof CharSequenceWithStringHash) {
// we know for sure these classes have conformant (and maybe faster) hashCode()
return chars.hashCode();
}
return stringHashCode(chars, 0, chars.length());
return Strings.stringHashCode(chars);
}
@Contract(pure = true)
@@ -1310,102 +1305,52 @@ public class StringUtil extends StringUtilRt {
@Contract(pure = true)
public static @NotNull <T> String join(T @NotNull [] items, @NotNull Function<? super T, String> f, @NotNull String separator) {
return join(Arrays.asList(items), f, separator);
return Strings.join(items, f, separator);
}
@Contract(pure = true)
public static @NotNull <T> String join(@NotNull Collection<? extends T> items,
@NotNull Function<? super T, String> f,
@NotNull String separator) {
if (items.isEmpty()) return "";
if (items.size() == 1) return notNullize(f.fun(items.iterator().next()));
return join((Iterable<? extends T>)items, f, separator);
return Strings.join(items, f, separator);
}
@Contract(pure = true)
public static @NotNull String join(@NotNull Iterable<?> items, @NotNull String separator) {
StringBuilder result = new StringBuilder();
for (Object item : items) {
result.append(item).append(separator);
}
if (result.length() > 0) {
result.setLength(result.length() - separator.length());
}
return result.toString();
return Strings.join(items, separator);
}
@Contract(pure = true)
public static @NotNull <T> String join(@NotNull Iterable<? extends T> items,
@NotNull Function<? super T, ? extends CharSequence> f,
@NotNull String separator) {
StringBuilder result = new StringBuilder();
join(items, f, separator, result);
return result.toString();
return Strings.join(items, f, separator);
}
public static <T> void join(@NotNull Iterable<? extends T> items,
@NotNull Function<? super T, ? extends CharSequence> f,
@NotNull String separator,
@NotNull StringBuilder result) {
boolean isFirst = true;
for (T item : items) {
CharSequence string = f.fun(item);
if (!isEmpty(string)) {
if (isFirst) {
isFirst = false;
}
else {
result.append(separator);
}
result.append(string);
}
}
Strings.join(items, f, separator, result);
}
@Contract(pure = true)
public static @NotNull String join(@NotNull Collection<String> strings, @NotNull String separator) {
if (strings.size() <= 1) {
return notNullize(strings.isEmpty() ? null : strings.iterator().next());
}
StringBuilder result = new StringBuilder();
join(strings, separator, result);
return result.toString();
return Strings.join(strings, separator);
}
public static void join(@NotNull Collection<String> strings, @NotNull String separator, @NotNull StringBuilder result) {
boolean isFirst = true;
for (String string : strings) {
if (string != null) {
if (isFirst) {
isFirst = false;
}
else {
result.append(separator);
}
result.append(string);
}
}
Strings.join(strings, separator, result);
}
@Contract(pure = true)
public static @NotNull String join(final int @NotNull [] strings, final @NotNull String separator) {
final StringBuilder result = new StringBuilder();
for (int i = 0; i < strings.length; i++) {
if (i > 0) result.append(separator);
result.append(strings[i]);
}
return result.toString();
return Strings.join(strings, separator);
}
@Contract(pure = true)
public static @NotNull String join(final String @NotNull ... strings) {
if (strings.length == 0) return "";
final StringBuilder builder = new StringBuilder();
for (final String string : strings) {
builder.append(string);
}
return builder.toString();
return Strings.join(strings);
}
@Contract(pure = true)
@@ -2683,7 +2628,6 @@ public class StringUtil extends StringUtilRt {
@Contract(pure = true)
public static @NotNull String formatLinks(@NotNull String message) {
@SuppressWarnings("HttpUrlsUsage")
Pattern linkPattern = Pattern.compile("http://[a-zA-Z0-9./\\-+]+");
StringBuffer result = new StringBuffer();
Matcher m = linkPattern.matcher(message);

View File

@@ -679,14 +679,6 @@ public final class ReflectionUtil {
return unsafe;
}
private static final class MySecurityManager extends SecurityManager {
private static final MySecurityManager INSTANCE = new MySecurityManager();
Class<?>[] getStack() {
return getClassContext();
}
}
/**
* Returns the class this method was called 'framesToSkip' frames up the caller hierarchy.
*
@@ -695,17 +687,8 @@ public final class ReflectionUtil {
* Please consider not using it.
* These aren't the droids you're looking for!</b>
*/
@Nullable
public static Class<?> findCallerClass(int framesToSkip) {
try {
Class<?>[] stack = MySecurityManager.INSTANCE.getStack();
int indexFromTop = 1 + framesToSkip;
return stack.length > indexFromTop ? stack[indexFromTop] : null;
}
catch (Exception e) {
LOG.warn(e);
return null;
}
return ReflectionUtilRt.findCallerClass(framesToSkip + 1);
}
public static boolean isAssignable(@NotNull Class<?> ancestor, @NotNull Class<?> descendant) {

View File

@@ -2512,35 +2512,35 @@ public final class ContainerUtil {
return CollectionFactory.createConcurrentWeakValueMap();
}
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "2021.3")
@Contract(value = "_,_,_,_ -> new", pure = true)
static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentWeakKeySoftValueMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
final @NotNull HashingStrategy<? super K> hashingStrategy) {
//noinspection deprecation
return new ConcurrentWeakKeySoftValueHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
return CollectionFactory.createConcurrentWeakKeySoftValueMap(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentSoftKeySoftValueMap() {
return new ConcurrentSoftKeySoftValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical());
return CollectionFactory.createConcurrentSoftKeySoftValueMap(100, 0.75f, Runtime.getRuntime().availableProcessors());
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakKeySoftValueMap() {
//noinspection deprecation
return new ConcurrentWeakKeySoftValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical());
return CollectionFactory.createConcurrentWeakKeySoftValueMap();
}
@Contract(value = " -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakKeyWeakValueMap() {
return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), HashingStrategy.canonical());
return CollectionFactory.createConcurrentWeakKeyWeakValueMap();
}
@ApiStatus.Internal
@Contract(value = "_ -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakKeyWeakValueMap(@NotNull HashingStrategy<? super K> strategy) {
return new ConcurrentWeakKeyWeakValueHashMap<>(100, 0.75f, Runtime.getRuntime().availableProcessors(), strategy);
return CollectionFactory.createConcurrentWeakKeyWeakValueMap(strategy);
}
@Contract(value = " -> new", pure = true)
@@ -2550,7 +2550,7 @@ public final class ContainerUtil {
@Contract(value = " -> new", pure = true)
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentSoftMap() {
return new ConcurrentSoftHashMap<>();
return CollectionFactory.createConcurrentSoftMap();
}
@Contract(value = " -> new", pure = true)
@@ -2559,12 +2559,14 @@ public final class ContainerUtil {
}
@ApiStatus.Internal
@ApiStatus.ScheduledForRemoval(inVersion = "2021.3")
@Deprecated
@Contract(value = "_,_,_,_ -> new", pure = true)
public static @NotNull <K, V> ConcurrentMap<K, V> createConcurrentSoftMap(int initialCapacity,
float loadFactor,
int concurrencyLevel,
@NotNull HashingStrategy<? super K> hashingStrategy) {
return new ConcurrentSoftHashMap<>(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
return CollectionFactory.createConcurrentSoftMap(initialCapacity, loadFactor, concurrencyLevel, hashingStrategy);
}
public static @NotNull <K> HashingStrategy<K> createHashingStrategy(@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
@@ -2582,7 +2584,7 @@ public final class ContainerUtil {
}
/**
* @deprecated Use {@link CollectionFactory#createConcurrentWeakMap(int, float, int)}
* @deprecated Use {@link CollectionFactory#createConcurrentWeakMap(int, float, int, HashingStrategy)}
* or {@link CollectionFactory#createConcurrentWeakIdentityMap()} (int, float, int)}.
*/
@Deprecated
@@ -2591,7 +2593,7 @@ public final class ContainerUtil {
float loadFactor,
int concurrencyLevel,
@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
return new ConcurrentWeakHashMap<>(initialCapacity, loadFactor, concurrencyLevel, createHashingStrategy(hashingStrategy));
return CollectionFactory.createConcurrentWeakMap(initialCapacity, loadFactor, concurrencyLevel, createHashingStrategy(hashingStrategy));
}
/**
@@ -2599,7 +2601,7 @@ public final class ContainerUtil {
*/
@Deprecated
public static @NotNull <K,V> ConcurrentMap<K,V> createConcurrentWeakMap(@NotNull TObjectHashingStrategy<? super K> hashingStrategy) {
return new ConcurrentWeakHashMap<>(createHashingStrategy(hashingStrategy));
return CollectionFactory.createConcurrentWeakMap(createHashingStrategy(hashingStrategy));
}
/**
@@ -2918,14 +2920,12 @@ public final class ContainerUtil {
@Contract(value = "_ -> new", pure = true)
public static @NotNull <K,V> Map<K,V> createWeakMap(int initialCapacity) {
//noinspection deprecation
return new WeakHashMap<>(initialCapacity, 0.8f, HashingStrategy.canonical());
return CollectionFactory.createWeakMap(initialCapacity, 0.8f, HashingStrategy.canonical());
}
@Contract(value = "_, _, _ -> new", pure = true)
public static @NotNull <K,V> Map<K,V> createWeakMap(int initialCapacity, float loadFactor, @NotNull HashingStrategy<? super K> strategy) {
//noinspection deprecation
return new WeakHashMap<>(initialCapacity, loadFactor, strategy);
public static @NotNull <K,V> Map<K,V> createWeakMap(int initialCapacity, float loadFactor, @NotNull HashingStrategy<? super K> strategy) {
return CollectionFactory.createWeakMap(initialCapacity, loadFactor, strategy);
}
@Contract(value = " -> new", pure = true)

View File

@@ -2,15 +2,15 @@
package com.intellij.openapi.util.text;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.Function;
import com.intellij.util.text.CharArrayCharSequence;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;
public final class Strings {
private static final List<String> REPLACES_REFS = Arrays.asList("&lt;", "&gt;", "&amp;", "&#39;", "&quot;");
@@ -423,6 +423,16 @@ public final class Strings {
return s;
}
@Contract(pure = true)
public static int stringHashCode(@NotNull CharSequence chars) {
if (chars instanceof String || chars instanceof CharSequenceWithStringHash) {
// we know for sure these classes have conformant (and maybe faster) hashCode()
return chars.hashCode();
}
return stringHashCode(chars, 0, chars.length());
}
@Contract(pure = true)
public static int stringHashCode(@NotNull CharSequence chars, int from, int to) {
return stringHashCode(chars, from, to, 0);
@@ -568,4 +578,104 @@ public final class Strings {
}
return result == null ? text : result.toString();
}
}
@Contract(pure = true)
public static @NotNull <T> String join(T @NotNull [] items, @NotNull Function<? super T, String> f, @NotNull String separator) {
return join(Arrays.asList(items), f, separator);
}
@Contract(pure = true)
public static @NotNull <T> String join(@NotNull Collection<? extends T> items,
@NotNull Function<? super T, String> f,
@NotNull String separator) {
if (items.isEmpty()) return "";
if (items.size() == 1) return notNullize(f.fun(items.iterator().next()));
return join((Iterable<? extends T>)items, f, separator);
}
@Contract(pure = true)
public static @NotNull String join(@NotNull Iterable<?> items, @NotNull String separator) {
StringBuilder result = new StringBuilder();
for (Object item : items) {
result.append(item).append(separator);
}
if (result.length() > 0) {
result.setLength(result.length() - separator.length());
}
return result.toString();
}
@Contract(pure = true)
public static @NotNull <T> String join(@NotNull Iterable<? extends T> items,
@NotNull Function<? super T, ? extends CharSequence> f,
@NotNull String separator) {
StringBuilder result = new StringBuilder();
join(items, f, separator, result);
return result.toString();
}
public static <T> void join(@NotNull Iterable<? extends T> items,
@NotNull Function<? super T, ? extends CharSequence> f,
@NotNull String separator,
@NotNull StringBuilder result) {
boolean isFirst = true;
for (T item : items) {
CharSequence string = f.fun(item);
if (!isEmpty(string)) {
if (isFirst) {
isFirst = false;
}
else {
result.append(separator);
}
result.append(string);
}
}
}
@Contract(pure = true)
public static @NotNull String join(@NotNull Collection<String> strings, @NotNull String separator) {
if (strings.size() <= 1) {
return notNullize(strings.isEmpty() ? null : strings.iterator().next());
}
StringBuilder result = new StringBuilder();
join(strings, separator, result);
return result.toString();
}
public static void join(@NotNull Collection<String> strings, @NotNull String separator, @NotNull StringBuilder result) {
boolean isFirst = true;
for (String string : strings) {
if (string != null) {
if (isFirst) {
isFirst = false;
}
else {
result.append(separator);
}
result.append(string);
}
}
}
@Contract(pure = true)
public static @NotNull String join(final int @NotNull [] strings, final @NotNull String separator) {
final StringBuilder result = new StringBuilder();
for (int i = 0; i < strings.length; i++) {
if (i > 0) result.append(separator);
result.append(strings[i]);
}
return result.toString();
}
@Contract(pure = true)
public static @NotNull String join(final String @NotNull ... strings) {
if (strings.length == 0) return "";
final StringBuilder builder = new StringBuilder();
for (final String string : strings) {
builder.append(string);
}
return builder.toString();
}
}