Java 继任人(候选人); 计数器--; } 返回rollOverToStart(计数器,候选者.iterator().next()); } 私有集合allLetters(){ Set letters=newlinkedhashset(); 字母=头; for(int i=0;i

Java 继任人(候选人); 计数器--; } 返回rollOverToStart(计数器,候选者.iterator().next()); } 私有集合allLetters(){ Set letters=newlinkedhashset(); 字母=头; for(int i=0;i,java,overriding,hashcode,circular-list,Java,Overriding,Hashcode,Circular List,在getstartofsmalestrotation中实现的算法找到单词的字典最小旋转,基本上就是我上面描述的:比较并选择每个旋转的字典最小的第一、第二、第三等字母,删除较大的字母,直到只剩下一个候选字母,或者你把这个词翻过来。因为列表是循环的,所以我使用计数器来避免无限循环 最后,如果我有一个单独的候选者,它可能在单词的中间,我需要开始最小的单词旋转。然而,由于这是一个单独链接的列表,因此在其中后退是很尴尬的。幸运的是,计数器很好地帮助了我:它记录了到目前为止我比较过的字母数量,但在循环列表中

getstartofsmalestrotation
中实现的算法找到单词的字典最小旋转,基本上就是我上面描述的:比较并选择每个旋转的字典最小的第一、第二、第三等字母,删除较大的字母,直到只剩下一个候选字母,或者你把这个词翻过来。因为列表是循环的,所以我使用计数器来避免无限循环

最后,如果我有一个单独的候选者,它可能在单词的中间,我需要开始最小的单词旋转。然而,由于这是一个单独链接的列表,因此在其中后退是很尴尬的。幸运的是,计数器很好地帮助了我:它记录了到目前为止我比较过的字母数量,但在循环列表中,这相当于我在翻滚之前可以向前移动的字母数量。因此,我知道要向前移动多少个字母,以便再次到达我正在寻找的最小单词旋转的开头


希望这有助于某人-至少写起来很有趣:-)

我误解了你的问题-我以为你想要不同的haschodes来表示“picture”和“turepic”;我认为在这种情况下,您可以从以下事实中得到一个提示:两个相等的对象必须具有相同的哈希代码,但具有相同哈希代码的两个对象不一定相等

因此,您可以使用Vivien的解决方案,该解决方案将保证“picture”和“turepic”具有相同的哈希代码。然而,这也意味着“picture”和“pitcure”也将具有相同的哈希代码。在这种情况下,您的
equals
方法必须更加智能,并且必须确定这两个字母列表是否代表同一个单词。本质上,equals方法有助于解决“picture”/“turepic”和“pitcure”之间的冲突

因为+是可交换的,所以相等的字将具有相等的哈希码。hashcode不是很有区别(所有字母排列都得到相同的hash码),但它应该可以做到这一点,除非您通常在HashSet中放入许多排列

注意:我添加了
c*c
,而不是简单地添加
c
,以减少不同字母的冲突

注2:哈希代码相等的不相等列表不违反哈希代码合同。应该避免这种“冲突”,因为它们会降低性能,但不会威胁程序的正确性。一般来说,冲突是无法避免的,尽管与我的回答相比,避免冲突的可能性肯定更大,但这样做会使哈希代码的计算成本更高,这可能会消耗更多的性能增益

  • 字母定义
    equals()
    hashCode()
    。仅使用
    char
    字段执行此操作
  • 对于
    CircularWord
    ,通过从
    head
    迭代到
    tail
    XOR'ing
    Letter.hashCode
    的相应值来实现
    hashCode()
    。最后用某个常数对结果进行异或运算

  • 另一种方法是规范化循环词,将其表示为:

    public class CircularWord {
    
        private static Set<String> canonicalWords = new HashSet<String>();
        private String canonicalWord;
        private int offset;
    
        public CircularWord(String word) {
            // Looks for an equal cirular word in the set (according to our definition)
            // If found, set canonicalWord to it and calculate the offset.
            // If not found, put the word in the set, set canonical word to our argument and set offset to 0.
        }
        // Implementation of CircularWord methods using
        // canonicalWord and offset
    }
    
    公共类循环词{
    私有静态集canonicalWords=new HashSet();
    私有字符串规范字;
    私有整数偏移;
    公共通告词(字符串字){
    //在集合中查找相等的循环词(根据我们的定义)
    //如果找到,将canonicalWord设置为它并计算偏移量。
    //如果找不到,则将单词放入集合中,将规范单词设置为参数,并将偏移量设置为0。
    }
    //循环词方法的实现
    //规范字和偏移量
    }
    

    然后,您可以通过委托给
    字符串
    实现来实现
    equals()
    hashCode()

    请记住,hashCode不是唯一的。两个不同的对象可以散列为完全相同的值。因此hashcode不足以确定相等性;您必须在equals()中进行实际比较。[已删除推测性评论。OMG]

    hashcode()在所有情况下都只能返回一个常量。这可能会影响性能,但它是完全有效的。完成所有其他工作后,就可以使用更高效的hashcode()算法了


    。注意“惰性哈希代码”部分。

    您真的需要使用哈希代码吗?如果不打算将对象成员放置在任何类型的哈希结构中,可以忽略以下问题:

    public int hashCode() {
        return 5;
    }
    
    这就满足了
    public class CircularWord {
        private final Letter head;
        private final int numberOfElements;
        
        // constructor, toString(), equals() omitted
    
        @Override
        public int hashCode() {
            return hashCodeStartingFrom(getStartOfSmallestRotation());
        }
    
        private Letter getStartOfSmallestRotation() {
            if (head == null) {
                return null;
            }
            Set<Letter> candidates = allLetters();
            int counter = numberOfElements;
    
            while (candidates.size() > 1 && counter > 0) {
                candidates = selectSmallestSuccessors(candidates);
                counter--;
            }
            return rollOverToStart(counter, candidates.iterator().next());
        }
    
        private Set<Letter> allLetters() {
            Set<Letter> letters = new LinkedHashSet<Letter>();
            Letter letter = head;
    
            for (int i = 0; i < numberOfElements; i++) {
                letters.add(letter);
                letter = letter.getNext();
            }
            return letters;
        }
    
        private Set<Letter> selectSmallestSuccessors(Set<Letter> candidates) {
            Set<Letter> smallestSuccessors = new LinkedHashSet<Letter>();
    
            char min = Character.MAX_VALUE;
            for (Letter letter : candidates) {
                Letter nextLetter = letter.getNext();
                if (nextLetter.getValue() < min) {
                    min = nextLetter.getValue();
                    smallestSuccessors.clear();
                }
                if (nextLetter.getValue() == min) {
                    smallestSuccessors.add(nextLetter);
                }
            }
            return smallestSuccessors;
        }
    
        private Letter rollOverToStart(int counter, Letter lastCandidate) {
            for (; counter >= 0; counter--) {
                lastCandidate = lastCandidate.getNext();
            }
            return lastCandidate;
        }
    
        private int hashCodeStartingFrom(Letter startFrom) {
            int hash = 0;
            Letter letter = startFrom;
            for (int i = 0; i < numberOfElements; i++) {
                hash = 31 * hash + letter.getValue();
                letter = letter.getNext();
            }
            return hash;
        }
    
    }
    
    int hashcode() {
        int hash = 0;
        for (c in list) {
            hash += c * c;
        }
        return hash;
    }
    
    public class CircularWord {
    
        private static Set<String> canonicalWords = new HashSet<String>();
        private String canonicalWord;
        private int offset;
    
        public CircularWord(String word) {
            // Looks for an equal cirular word in the set (according to our definition)
            // If found, set canonicalWord to it and calculate the offset.
            // If not found, put the word in the set, set canonical word to our argument and set offset to 0.
        }
        // Implementation of CircularWord methods using
        // canonicalWord and offset
    }
    
    public int hashCode() {
        return 5;
    }
    
    hash = 0
    for each rotation
        hash += hash(permutation)
    end
    hash %= MAX_HASH