如何在不改变equals和hashcode的情况下插入到set中

时间:2012-09-20 07:59:27

标签: java groovy set guava hashset

我正在寻找建议。 我有一个Person类,其中包含String firstName和String lastName 当我想要使用相同的字符串插入列表值时:

set.add(new Person("firstName","lastName"))

set.add(new Person("firstName","lastName"))

该集合不会过滤对象,但它们仍会进入集合。 有没有建议创建集合列表而不重写equales和hashcode函数? 也许用番石榴或一些groovy列表? 谢谢, 或

4 个答案:

答案 0 :(得分:11)

在番石榴中有一个Equivalence课程,专门针对这些事情。像这样创建自己的Equivalence类:

import com.google.common.base.Equivalence;
import com.google.common.base.Objects;

public class PersonEquivalence extends Equivalence<Person> {

  @Override
  protected boolean doEquivalent(Person p1, Person p2) {
    return Objects.equal(p1.getFistName(), p2.getFistName())
        && Objects.equal(p1.getLastName(), p2.getLastName());
  }

  @Override
  protected int doHash(Person person) {
    return Objects.hashCode(person.getFistName(), person.getLastName());
  }

}

然后是这段代码

Set<Equivalence.Wrapper<Person>> set = Sets.newHashSet();
PersonEquivalence personEquivalence = new PersonEquivalence();
set.add(personEquivalence.wrap(new Person("Joe", "Doe")));
set.add(personEquivalence.wrap(new Person("Joe", "Doe")));
set.add(personEquivalence.wrap(new Person("Jane", "Doe")));
System.out.println(set);

打印

[PersonEquivalence@8813f2.wrap(Person{firstName=Jane, lastName=Doe}),
 PersonEquivalence@8813f2.wrap(Person{firstName=Joe, lastName=Doe})]

当然它有点冗长,但你可以创建ForwardingSet来自动包装和解包Person

答案 1 :(得分:4)

您可以使用自己的比较器创建TreeSet

Set<Person> set = new TreeSet<Person>(new Comparator<Person>() {
    @Override
    public int compare(Person p1, Person p2) {
        // Your own compare logic
    }
});

答案 2 :(得分:4)

你不能违反Set的合同。要么不使用Set,要么将Person包装在另一个根据内部equals实现hashcodePerson的类中(请参阅其他答案)为了在番石榴中做到这一点。

答案 3 :(得分:0)

这是对我的地图建议的粗略尝试。

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

public class PeopleCarrier implements Iterable<Person>{

    private Map<PersonKey, Person> storage = new HashMap<PersonKey, Person>();

    public void add(Person p) {
        PersonKey pk = new PersonKey(p);
        storage.put(pk, p);     
    }

    public boolean contains(Person p) {
        return storage.containsKey(new PersonKey(p));
    }

    @Override
    public Iterator<Person> iterator() {
        return new Iterator<Person>() {

            private Iterator<PersonKey> i = storage.keySet().iterator();

            @Override
            public void remove() {
                throw new UnsupportedOperationException();
            }

            @Override
            public Person next() {
                return storage.get(i.next());               
            }

            @Override
            public boolean hasNext() {
                return i.hasNext();
            }
        };
    }

    private class PersonKey {
        private String firstname;
        private String lastname;
        public PersonKey(Person p) {
            this.firstname = p.getFirstname();
            this.lastname = p.getLastname();
        }
        /* (non-Javadoc)
         * @see java.lang.Object#hashCode()
         */
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + getOuterType().hashCode();
            result = prime * result
                    + ((firstname == null) ? 0 : firstname.hashCode());
            result = prime * result
                    + ((lastname == null) ? 0 : lastname.hashCode());
            return result;
        }
        /* (non-Javadoc)
         * @see java.lang.Object#equals(java.lang.Object)
         */
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (!(obj instanceof PersonKey))
                return false;
            PersonKey other = (PersonKey) obj;
            if (!getOuterType().equals(other.getOuterType()))
                return false;
            if (firstname == null) {
                if (other.firstname != null)
                    return false;
            } else if (!firstname.equals(other.firstname))
                return false;
            if (lastname == null) {
                if (other.lastname != null)
                    return false;
            } else if (!lastname.equals(other.lastname))
                return false;
            return true;
        }
        private PeopleCarrier getOuterType() {
            return PeopleCarrier.this;
        }   

    }
}