java - 装饰器模式和哈希码

标签 java design-patterns hash

我在我的一个程序中使用装饰器模式来装饰具有不同毕业要求的类(class)。几个例子:

new BasicCourse("Course Foo", 1);  // parameters are name and credits

new DisciplinaryBreadth(DBR.MATH, new BasicCourse("Course Foo", 1));

new IntroToHumanities(IHUM.FIRST_QUARTER,
        new ProgramInWritingAndRhetoric(PWR.FIRST_YEAR,
        new BasicCourse("Course Bar", 2)));

new ProgramInWritingAndRhetoric(PWR.FIRST_YEAR,
        new IntroToHumanities(IHUM.FIRST_QUARTER,
        new BasicCourse("Course Bar", 2)));

根据交换律,后两者是相同的。

我正在实现 hashcode()equals(),以便我可以在 HashMap 中使用类(class)。我必须更改 Eclipse 自动生成的 equals 函数,以便可交换的类(class)彼此相等。我对 hashcode 生成的理解不如 equals 那样,所以我想知道是否需要对 hashcode 函数做同样的事情。

这是 Eclipse 为我提供的每个装饰器的内容:

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((inner == null) ? 0 : inner.hashCode());
        result = prime * result
                + ((requirement == null) ? 0 : requirement.hashCode());
        return result;
    }

这会为交换类(class)产生相同的哈希值吗?

编辑
每个装饰器都有一个 requirement 变量,该变量对应于带有该装饰器的类(class)满足的要求。例如,DisciplinaryBreadth 类具有 DBR 类的要求,该类是可能的 Disciplinary Breadth 要求的枚举。 ProgramInWritingAndRhetoric 类具有 PWR 类的要求,该类是可能的写作和修辞程序要求的枚举。等等。

每个装饰器中的需求变量是不同的枚举。所有类(class)都实现了获取各种毕业要求的方法(例如 getDbrs()getIhum())。

装饰器调用其内部类(class)的方法来满足除他们定义的要求之外的所有要求。例如,IntroToHumanities 类调用 inner.getDbrs()inner.getPwr(),但将其需求变量用于其 getIhum() 方法。他们还为 getName()getCredits() 方法调用其内部 Course 的方法,而 BasicCourse 类使用其构造函数中设置的最终成员来定义这些方法。

inner 变量只是每个装饰器包装的内部 Course。内部变量和需求变量在每个装饰器的构造函数中设置,并且是最终的。

这是我的 ProgramInWritingAndRhetoric 类的 equals 方法:

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (!(obj instanceof Course))
        return false;
    Course other = (Course) obj;
    if (getName() == null) {
        if (other.getName() != null)
            return false;
    } else if (!getName().equals(other.getName()))
        return false;
    if (getCredits() != other.getCredits())
        return false;
    if (!getDbrs().equals(other.getDbrs()))
        return false;
    if (!requirement.equals(other.getPwr()))
        return false;
    if (!getIhum().equals(other.getIhum()))
        return false;
    if (!getEc().equals(other.getEc()))  //another Graduation Requirement
        return false;
    return true;
}

我跳过了一些对 null 的检查,因为我在构造函数中检查了它们,因此,例如,您不能使用 null IHUM 来制作类(class)。其他毕业要求实现也类似,唯一的区别在于使用要求变量的位置。

最佳答案

@Eva 我不同意你应该让 IDE 生成哈希码方法的建议,但也许我很老式。

基本上,在生成哈希时,您的目标是(在合理可行的范围内)基于对象的成员变量获得一组分布良好且唯一的哈希。

因此,您应该获取成员变量的值(如果是原语)或哈希码(如果是复杂对象),并使用它们以分布良好的方式计算哈希码(因此通常使用素数)作为乘数)并且不太可能引起碰撞。

因此,合理的 hashCode() 将使用与 equals 方法相同的成员变量,但获取值/哈希值并将它们与素数相乘。

请记住,唯一的、分布良好的哈希值的唯一保证是提前了解可能存在的全部对象,在这种情况下,您实际上可以预先分配哈希值,但这很少是有效的解决方案。

这很好地解释了您想要实现的目标 - http://eclipsesource.com/blogs/2012/09/04/the-3-things-you-should-know-about-hashcode/

关于java - 装饰器模式和哈希码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14484705/

相关文章:

java - Android 自定义通知 RemoView 不使用样式

Linux/Unix 替换字符串中的模式并使用 sed 保存到新文件

javascript - 从 DOM 元素中提取属性

java - 为什么Eclipse生成的hashCode()方法返回的哈希码不太好?

.net - .NET Framework 中是否使用了任何设计模式?

algorithm - 我什么时候应该重新哈希整个哈希表?

java - org.apache.camel.InvalidPayloadException:没有可用类型为java.io.InputStream的主体,但具有值:在解码绑定(bind)bean时抛出

java - 为什么我可以在 Java 中将按位运算符与数学运算符(如 &+)结合使用?

java - Java 中的链接按钮和文本字段数组

android - Android 开发的架构模式