Java 添加到集合时防止重复

Java 添加到集合时防止重复,java,duplicates,add,hashset,comparator,Java,Duplicates,Add,Hashset,Comparator,情况: 假设我有一个这样的类: class Person { public String name; public String surname; public age; } 现在,我想创建一个集合,其中包含一些人,这些人基于先前创建的列表(包含一些重复项)。当然,当我创建集合时,我不想在里面有任何副本 HashSet<Person> mySet = new LinkedHashSet<Person>(listOfPeople); 问题: 因此

情况:

假设我有一个这样的类:

class Person {
    public String name;
    public String surname;
    public age;
}
现在,我想创建一个集合,其中包含一些人,这些人基于先前创建的列表(包含一些重复项)。当然,当我创建集合时,我不想在里面有任何副本

HashSet<Person> mySet = new LinkedHashSet<Person>(listOfPeople);
问题: 因此,我明白我应该简单地重写
Person
中的
equals
,并记住为根据我的要求应该“相等”的对象返回相同的
hashCode
。但是,如果我的“平等”术语在运行时发生变化,该怎么办

我这样问是因为在使用
Collections.sort对集合进行排序时,我可以指定一个自定义的
比较器
,它使我能够根据情况提供比较逻辑

您知道有没有类似的机制或解决方案可以让我在运行时决定在创建一组元素时组件是否相等

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

我现在唯一的解决方案是在Person类中定义一些静态比较器,然后以使用此比较器的方式重写equals方法

不要那样做。
比较器
契约中的任何内容都不要求对
.equals()
不同的两个对象进行非零比较。唯一可以设置的约束条件是,如果两个对象是
.equals()
,则它们之间的比较结果为0。
compariable
的实现被称为“与equals兼容”。但是有些类在JDK中甚至不尊重这一点(请参见
BigDecimal

你有两个选择:

  • 使用
    SortedSet
    。例如,
    TreeSet
    允许您在运行时传递
    比较器。无论
    .equals()
    如何,一个
    SortedSet
    计算等价性的结果是,两个实例相互比较得到0
  • 如果您使用番石榴,您可以为您的对象创建一个或多个s;然后,您的
    集合
    必须具有类型为
    等效的成员。Wrapper
    而不仅仅是
    Person
    ,并且您必须
    。添加(eq.wrapp(Person))
    ,但它可以工作

您可以将
TreeSet
与您自己的比较器一起使用

您必须修改Person类中的一些内容,并使用此自定义哈希集

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;
    }   

}
在hashcode方法重复检查中使用您自己的逻辑

测试

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);
}
} 这将只添加一个元素。不允许重复元素。 希望这对你有帮助。 你也可以使用类似的接口实现。

是的,我也想到了一个“包装器”关键字!我认为这是非常复杂的。但可能不是。谢谢你的提示!
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);
}