添加到set时防止重复

时间:2014-04-01 09:20:07

标签: java duplicates add hashset comparator

情况:

我们假设我有一个这样的课程:

class Person {
    public String name;
    public String surname;
    public age;
}

现在我想根据一些prevoiusly创建的列表(包含一些重复项)创建一个包含一些People的集合。当然,当我创建集合时,我不希望内部有任何重复。

HashSet<Person> mySet = new LinkedHashSet<Person>(listOfPeople);

问题: 让我们假设,在某些情况下,&#34;没有重复&#34; 对我来说意味着&#34;具有不同名称的人&#34; 。在其他情况下&#34;年龄不同的人&#34;

我发现HashSet的{​​{1}}方法使用add中的put

HashMap

问题: 所以,我知道我应该简单地覆盖public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { // <== !! V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; } 中的equals,并记住为对象应该返回相同的Person,这些对象应该是&#34;等于&#34;根据我的要求。但是,如果我的平等&#34;运行期间的术语变化?

我问,因为在使用hashCode对系列进行排序时,我可以指定一个自定义Collections.sort,这使我能够根据情况提供比较逻辑。

是否有任何类比机制或解决方案,使我能够在运行时决定创建一组元素时组件是否相等?

我现在唯一的解决方案是在Person类中定义一些静态Comparator,然后以这种方式覆盖equals方法它使用这个比较器。然后,通过亲自替换比较器我实际上改变了等于逻辑......这有意义吗?

3 个答案:

答案 0 :(得分:1)

  

我现在唯一的解决方案是在Person类中定义一些静态Comparator,然后以这种方式覆盖equals方法它使用这个比较器

不要那样做。 Comparator合同中的任何内容都不需要将与.equals()不同的两个对象与非零进行比较。可以放置的唯一约束是如果两个对象是.equals()然后相互比较它们给出0. Comparable的实现被认为是“兼容的等于”。但有些类甚至不尊重JDK中的内容(参见BigDecimal)。

您有两种选择:

  • 使用SortedSet。例如TreeSet允许您在运行时传递ComparatorSortedSet评估两个实例相互比较为0的事实的等价性,无论.equals()如何。
  • 如果您使用Guava,您可以为对象创建一个或多个Equivalence;然后,您的Set必须包含Equivalence.Wrapper<Person>类型的成员,而不仅仅是Person,而您必须.add(eq.wrap(person)),但这样做有效。

答案 1 :(得分:0)

您可以将TreeSet<Person>与您自己的比较器

一起使用

答案 2 :(得分:0)

你必须在Person类中修改一下并使用这个自定义的hashSet

public class CustomHashSet extends HashSet {        
    @Override
    public boolean add(Object e) {
        boolean flag  = true;
        Iterator<Object> itr = this.iterator();
        while(itr.hasNext()){
            if(itr.next().hashCode()==(e.hashCode())){
                flag = false;
                break;
            }
        }
        if(flag)
            flag = flag & super.add(e);
        return flag;
    }   

}

人员类中的修改

public class Person {

    public String name;
    public String surname;
    public int age;


    @Override
    public boolean equals(Object obj) {
         return (this == obj); 
    }

    @Override
    public int hashCode() {
          int result = name.hashCode();
            result = 31 * result + age;
            return result;
    }
}

在哈希码方法复制检查中使用您自己的逻辑。

测试

public class TestB {

public static void main(String[] args) {
    HashSet a = new CustomHashSet();
    Person p = new Person("test","test1",1);
    Person p1 = new Person("test","test1",1);
    a.add(p);
    a.add(p1);
    System.out.println(a);
}

} 这将只添加一个不允许的元素重复元素。 希望这对你有所帮助。 U也可以使用类似的接口实现。