Java 如何避免意外的哈希键操作

Java 如何避免意外的哈希键操作,java,hash,Java,Hash,我注意到向列表中添加元素确实会更改其哈希键值,因此无法再次访问它,因为.contains(modifiedObject)在这里不会发生冲突。我没想到这种行为是诚实的。让我想知道HashSet是如何进行散列的。。因此,如何确保在修改字符串列表时不破坏我的哈希集,如下所示。有没有一种方法可以安全地做到这一点,或者这只是我作为一名程序员必须注意的事情 private HashSet<List<String>> bagOfWordsMap = new HashSet<Lis

我注意到向列表中添加元素确实会更改其哈希键值,因此无法再次访问它,因为
.contains(modifiedObject)
在这里不会发生冲突。我没想到这种行为是诚实的。让我想知道
HashSet
是如何进行散列的。。因此,如何确保在修改字符串列表时不破坏我的
哈希集
,如下所示。有没有一种方法可以安全地做到这一点,或者这只是我作为一名程序员必须注意的事情

private HashSet<List<String>> bagOfWordsMap = new HashSet<List<String>>();

private void createBagOfWordsList(UnifiedTag[] invalidTags) {


    for(List<String> sentences : getSentenceList()) {

        List<String> sentenceStemWords = new ArrayList<String>();

        // Not what you would want to do since sentenceStemWords is 
        // modified right after and bagOfWordsMap.contains(sentenceStemWords)
        // won't collide again:

        // bagOfWordsMap.add(sentenceStemWords);

        for(String word : sentences) {

            String stem = Stemmer.getStem(word);
            sentenceStemWords.add(stem);
        }   

        bagOfWordsMap.add(sentenceStemWords);           
    }
}
private HashSet bagOfWordsMap=new HashSet();
私有void createBagOfWordsList(UnifiedTag[]invalidTags){
for(列出句子:getSentenceList()){
List SENTENCESTEMWORD=new ArrayList();
//不是你想做的,因为sentenceStemWords是
//在和bagOfWordsMap.contains之后修改(语句StemWords)
//不会再次碰撞:
//bagOfWordsMap.add(句子词条);
for(字符串:句子){
String stem=Stemmer.getStem(word);
添加(词干);
}   
bagOfWordsMap.add(句子词条);
}
}

一种方法是在
哈希集中使用
不可修改列表
而不是
列表

另一种选择是使用
哈希映射
而不是
哈希集
,前提是您可以将一些唯一的
字符串
键与每个
列表
关联。

切勿将可变对象用作映射或集合中的键 如果要防止意外修改,请实现无法再修改的冻结类型

  • 细节:如果对象上的可变属性不改变键,那么从技术上讲,在对象上拥有这些属性是可以的,但是在java集中,您无法通过键轻松访问它们,因为没有
    HashSet。get
    要获取当前成员,只有
    包含
    。而且,它的风格不好,易碎。最好将这些对象拆分为键、值

那么我很确定OP首先无法将其添加到列表中?@christopher这将迫使他从哈希集中删除一个列表,并添加一个包含修改内容的新列表。虽然这会带来一些性能成本,但它可以防止损坏哈希集。对不起,太早了+1.好的,我想这也是一个有效的解决方案,但只有在我a)不允许操纵我的
列表
和b)必须接受这样一个事实,即我只允许在初始化对象后将其添加到哈希映射。@StefanFalk什么哈希映射?您的代码使用哈希集。如果将列表作为值保存在HashMap中(并决定某个唯一的不可变键),在将它们添加到映射后,您可以修改它们。您是否尝试过覆盖您所创建的
ArrayList
的某个子类中的
equals
hashCode
方法?@christopher:
equals
的有用/有意义的替代定义是什么?也许可以将列表中的值整理为一些格式?在
C
中,我可能会考虑在内存中散列对象的起始地址,我不知道这是否明智,但我想这将是一种方法,可以确保您始终获得您以后想要访问的对象。我不确定是否或如何在Java中做这样的事情,但重写
hashCode
似乎是一个可能的解决方案。我感觉问题在于
Set
不是您想要的正确数据结构。为什么是
集合
而不是其他东西?你如何从集合中获取列表?