当许多密钥具有相同的哈希码时,Java 8的HashMap如何退化为平衡树?我读到了键应该实现Comparable来定义一个顺序.HashMap如何结合散列和自然排序来实现树?那些没有实现的类Comparable,或者当多个不可相互比较的Comparable实现是同一个映射中的键时呢?
这就是我在做的事情:
List scores = Stream.concat(oldEntries.stream(), newEntries.stream())
.sorted()
.distinct()
.limit(maxSize)
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
我期待一个没有任何重复的排序列表,但有时候列表中有重复.
我已经覆盖了hashCode和equals方法,我还观察到这些方法每次都返回正确的值.任何人都可以看到我的流有什么问题吗?
这是我的equals()和hashCode()它们由IDEA自动生成:
..
private int userId;
private int levelId;
private int score;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Score score = (Score) o;
if (userId != score.userId) return false;
return levelId == score.levelId;
}
@Override
public int hashCode() {
int result = userId;
result = 31 * result + levelId;
return result;
} …Run Code Online (Sandbox Code Playgroud) 我们面临着自Java 8以来HashMap行为方式的奇怪问题.
当HashMap键实现Comparable接口但是compareTo实现与equals不一致时HashMaps:
他们应该成长得更大
它们包含几个相等元素的实例
附加到这些元素的值可能不同
get(key)结果取决于使用哪个键(即使键根据equals方法相等).
我创建了一个小测试来重现问题(见下文).测试总是通过Java 7(可能还有以前的版本).Java 8中的测试总是失败(除非我从类中删除了Comparable接口).
我不确定这是多么可以修复,如果没有可能在javadoc中显式下划线,那么如果要在哈希集合中使用对象,则必须与equals保持一致.
import java.util.HashMap;
import java.util.Map;
public class HashMapTest {
private static final char MIN_NAME = 'A';
private static final char MAX_NAME = 'K';
private static final int EXPECTED_NUMBER_OF_ELEMENTS = MAX_NAME - MIN_NAME + 1;
private HashMap<Person, Integer> personToAgeMap;
HashMapTest() {
personToAgeMap = new HashMap();
}
public static void main(String[] args) {
HashMapTest objHashMap = new HashMapTest();
System.out.println("Initial Size of Map: "
+ objHashMap.getPersonToAgeMap().size());
objHashMap.whenOverridingEqualElements_thenSizeOfTheMapIsStable();
objHashMap.whenGettingElementUsingPersonOfAge1_thenOverridenValuesAreReturned();
objHashMap.whenGettingElementUsingPersonOfAge100_thenOverridenValuesAreReturned();
objHashMap.whenGettingElementUsingPersonOfAge50_thenOverridenValuesAreReturned();
objHashMap
.whenGettingElementUsingPersonOfAgeMinus1_thenOverridenValuesAreReturned();
} …Run Code Online (Sandbox Code Playgroud)