2016-12-16 46 views
0

我一类叫做Skill为:搜索一个基类的对象在一组派生

public class Skill { 
    private final int type; 
    private final int level; 

    public Skill(int type, int level) { 
     this.type = type; 
     this.level = level; 
    } 

    // Getters 

    @Override 
    public int hashCode() { 
     int h = 17; 
     h = 31 * h + type; 
     h = 31 * h + level; 
     return h; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj instanceof Skill) { 
      Skill that = (Skill) obj; 
      return this.type == that.type && this.level == that.level; 
     } 
     return false; 
    } 
} 

另一个叫PSkill为:

public class PSkill extends Skill { 
    private final int preferenceLevel; 
    private final boolean mandatory; 

    public PSkill(int type, int level, int preferenceLevel, boolean mandatory) { 
     super(type, level); 
     this.preferenceLevel = preferenceLevel; 
     this.mandatory = mandatory; 
    } 

    // Getters 

    @Override 
    public int hashCode() { 
     return super.hashCode(); 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj instanceof PSkill) { 
      PSkill that = (PSkill) obj; 
      return super.equals(obj) 
       && this.preferenceLevel == that.preferenceLevel 
       && this.mandatory == that.mandatory; 
     } 
     return false; 
    } 
} 

我的要求: 搜索一设置PSkill对象以找到与Skill对象匹配的对象。 例如:Skill - type:1, level:2PSkill - type:1, level:2, preferenceLevel: any, mandatory: any的匹配

当我运行下面的代码时,它可以工作。

public class Invoker { 
    public static void main(String[] args) { 
     Set<PSkill> skills = new HashSet<>(Arrays.asList(new PSkill(1, 1, 1, true), new PSkill(1, 2, 1, true))); 
     System.out.println(skills.contains(new Skill(1, 1))); // prints true 
     System.out.println(skills.contains(new Skill(1, 3))); // prints false 
    } 
} 

而且我知道为什么,因为hashCode()实施这两种类型是相同的,在HashSet实施,key.equals(k)被使用,在我的情况下,关键是Skill对象,因此,平等的工作。

从HashSet的实现

final Node<K,V> getNode(int hash, Object key) { 
    Node<K,V>[] tab; Node<K,V> first, e; int n; K k; 
    if ((tab = table) != null && (n = tab.length) > 0 && 
     (first = tab[(n - 1) & hash]) != null) { 
     if (first.hash == hash && // always check first node 
      ((k = first.key) == key || (key != null && key.equals(k)))) // here 
      return first; 
     if ((e = first.next) != null) { 
      if (first instanceof TreeNode) 
       return ((TreeNode<K,V>)first).getTreeNode(hash, key); 
      do { 
       if (e.hash == hash && 
        ((k = e.key) == key || (key != null && key.equals(k)))) // and here 
        return e; 
      } while ((e = e.next) != null); 
     } 
    } 
    return null; 
} 

我知道我打破了hashCode()equals()合同。但代码正常工作,即检查Skill是否与该集合中的任何PSkill相匹配。

我的问题是: 是平等检查key.equals(k)HashSet依赖于实现,并可能在以后的版本即k.equals(key)予以转回,该代码将停止工作? 此外,如果没有简单地循环收集,任何更好的方法可以使它更脆弱。谢谢

+0

如果您更改插入顺序,它仍然可以工作吗? – AdamSkywalker

+0

@AdamSkywalker将'PSkill'对象插入集合中的顺序改变了吗?嗯,是。 – GurV

回答

0

这种行为当然不能保证。合同是,如果你提供了hashCode和equals的正确实现,你会得到一个hashset的正确实现。如果你没有遵循合同的结束,那么你不能保证一套产品的效果。

相关问题