diff options
author | Tor Norbye <tnorbye@google.com> | 2014-09-04 13:24:04 -0700 |
---|---|---|
committer | Tor Norbye <tnorbye@google.com> | 2014-09-04 13:24:04 -0700 |
commit | c3d3a90f6b4ead083d63e28e6b9fcea93d675678 (patch) | |
tree | fc0dcd722b6d445468dbe7dad13b4c11781b1cbe /platform/analysis-impl/src/com/intellij/codeInspection/SmartHashMap.java | |
parent | 1aa2e09bdbd413eacb677e9fa4b50630530d0656 (diff) | |
download | idea-c3d3a90f6b4ead083d63e28e6b9fcea93d675678.tar.gz |
Snapshot idea/138.1980 from git://git.jetbrains.org/idea/community.git
Change-Id: Ib567c9c152d770212a7a3db20fbf591c210920bd
Diffstat (limited to 'platform/analysis-impl/src/com/intellij/codeInspection/SmartHashMap.java')
-rw-r--r-- | platform/analysis-impl/src/com/intellij/codeInspection/SmartHashMap.java | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/SmartHashMap.java b/platform/analysis-impl/src/com/intellij/codeInspection/SmartHashMap.java new file mode 100644 index 000000000000..e66ae1ee379f --- /dev/null +++ b/platform/analysis-impl/src/com/intellij/codeInspection/SmartHashMap.java @@ -0,0 +1,206 @@ +/* + * Copyright 2000-2014 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. + */ +package com.intellij.codeInspection; + +import com.intellij.openapi.util.Comparing; +import com.intellij.util.IncorrectOperationException; +import com.intellij.util.SingletonSet; +import gnu.trove.THashMap; +import gnu.trove.TObjectFunction; +import gnu.trove.TObjectObjectProcedure; +import gnu.trove.TObjectProcedure; +import org.jetbrains.annotations.NotNull; + +import java.util.AbstractMap; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +/** + * Hash set (based on THashSet) which is fast when contains one or zero elements (avoids to calculate hash codes and call equals whenever possible). + * For other sizes it delegates to THashSet. + * Null keys are NOT PERMITTED. + */ +public class SmartHashMap<K,V> extends THashMap<K,V> { + private K theKey; // contains the only element if size() == 1 + private V theValue; + + @Override + public boolean containsKey(@NotNull Object key) { + K theKey = this.theKey; + if (theKey != null) { + return eq(theKey, (K)key); + } + return !super.isEmpty() && super.containsKey(key); + } + + @Override + public V put(@NotNull K key, V value) { + K theKey = this.theKey; + if (theKey != null) { + if (eq(theKey, key)) return theValue; + super.put(theKey, theValue); + this.theKey = null; + // fallthrough + } + else if (super.isEmpty()) { + this.theKey = key; + theValue = value; + return null; + } + return super.put(key, value); + } + + private boolean eq(K obj, K theKey) { + return theKey == obj || _hashingStrategy.equals(theKey, obj); + } + + @Override + public boolean equals(@NotNull Object other) { + K theKey = this.theKey; + if (theKey != null) { + if (!(other instanceof Map) || ((Map)other).size() != 1 ) return false; + Map.Entry<K, V> entry = ((Map<K, V>)other).entrySet().iterator().next(); + return eq(theKey, entry.getKey()) && Comparing.equal(theValue, entry.getValue()); + } + + return super.equals(other); + } + + @Override + public int hashCode() { + K theKey = this.theKey; + if (theKey != null) { + return _hashingStrategy.computeHashCode(theKey); + } + return super.hashCode(); + } + + @Override + public void clear() { + theKey = null; + theValue = null; + super.clear(); + } + + @Override + public int size() { + K theKey = this.theKey; + if (theKey != null) { + return 1; + } + return super.size(); + } + + @Override + public boolean isEmpty() { + K theKey = this.theKey; + return theKey == null && super.isEmpty(); + } + + @Override + public V remove(@NotNull Object obj) { + K theKey = this.theKey; + if (theKey != null) { + if (eq(theKey, (K)obj)) { + this.theKey = null; + V value = theValue; + theValue = null; + return value; + } + return null; + } + return super.remove(obj); + } + + @NotNull + @Override + public Set<K> keySet() { + K theKey = this.theKey; + if (theKey != null) { + return new SingletonSet<K>(theKey); + } + return super.keySet(); + } + + @NotNull + @Override + public Collection<V> values() { + K theKey = this.theKey; + if (theKey != null) { + return new SingletonSet<V>(theValue); + } + return super.values(); + } + + @NotNull + @Override + public Set<Map.Entry<K, V>> entrySet() { + K theKey = this.theKey; + if (theKey != null) { + return new SingletonSet<Map.Entry<K, V>>(new AbstractMap.SimpleEntry<K, V>(theKey, theValue)); + } + return super.entrySet(); + } + + @Override + public V get(Object key) { + K theKey = this.theKey; + if (theKey != null) { + return eq(theKey, (K)key) ? theValue : null; + } + return super.get(key); + } + + @Override + public boolean containsValue(Object val) { + K theKey = this.theKey; + if (theKey != null) { + return Comparing.equal(theValue, val); + } + return super.containsValue(val); + } + + @Override + public THashMap<K, V> clone() { + throw new IncorrectOperationException(); + } + + @Override + public void transformValues(TObjectFunction<V, V> function) { + throw new IncorrectOperationException(); + } + + @Override + public boolean retainEntries(TObjectObjectProcedure<K, V> procedure) { + throw new IncorrectOperationException(); + } + + @Override + public boolean forEachEntry(TObjectObjectProcedure<K, V> procedure) { + throw new IncorrectOperationException(); + } + + @Override + public boolean forEachValue(TObjectProcedure<V> procedure) { + throw new IncorrectOperationException(); + } + + @Override + public boolean forEachKey(TObjectProcedure<K> procedure) { + throw new IncorrectOperationException(); + } +} |