3

How can I fill a Set by objects with unique field ?

For example I have a class Person which has an unique field called name thus if I add to Set an object with duplicate name it should not be added.

public class Test {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Set<Person> objList = new HashSet<Person>();
        objList.add(new Person("John", "New York", "Accountant"));
        objList.add(new Person("Bill", "London", "Manager"));
        objList.add(new Person("John", "New York", "Driver"));// this object should not be added

        for(Person o : objList){
            System.out.println(o.name);//here should printed only John and Bill
        }
    }
}

class Person {
    String name;//must be unique
    String city;
    String position;

    public Person(String c_name, String c_city, String c_position){
        this.name = c_name;
        this.city = c_city;
        this.position = c_position;
    }
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
gigs
  • 1,241
  • 2
  • 15
  • 25
  • Possible duplicate of http://stackoverflow.com/questions/16009027/java-collection-of-unique-elements. – Neria Nachum Jul 02 '16 at 20:28
  • Neria Nachum, I can't understand how to override hashCode and equals methods for my example. – gigs Jul 02 '16 at 20:31
  • The google for it. Or ask your IDE to generate it for you, then try understanding the code and understanding how it compiles with the contract defined in the javadoc. – JB Nizet Jul 02 '16 at 20:33
  • Here's an implementation example: http://stackoverflow.com/questions/5396939/hashcode-and-equals-for-hashset – Neria Nachum Jul 02 '16 at 20:33

3 Answers3

2

In other words, you mean the person's name defines it's identity. You can produce such a behavior by overriding the equals(Object) and hashCode methods to include only it:

public class Person {
    // members, constructors, etc.

    @Override
    public boolean equals(Object other) {
        if (!(other instanceof Person)) {
            return false;
        }
        return name.equals(((Person)other).name);
    }

    @Override
    public int hashCode() {
        return name.hashCode();
    }
}
Mureinik
  • 297,002
  • 52
  • 306
  • 350
1

You need to overrride the equals() and hashcode() methods of Object class in Person class to achive this. Since you have not done that for HashSet all object of Person class is different and hashSet will allow you to add all Person.

Below is the code snippet for Person class for unique name only.

class Person{
    String name;//must be unique
    String city;
    String position;

    public Person(String c_name, String c_city, String c_position){
        this.name = c_name;
        this.city = c_city;
        this.position = c_position;
    }

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person other = (Person) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

}
sauumum
  • 1,638
  • 1
  • 19
  • 36
1

You can use UnifiedSetWithHashingStrategy from Eclipse Collections to define your own custom hashing strategy for your Set. The following code will work for your example.

HashingStrategy<Person> uniqueNameStrategy = new HashingStrategy<Person>() {
    @Override
    public int computeHashCode(Person person) {
        return person.name.hashCode();
    }

    @Override
    public boolean equals(Person person1, Person person2) {
        return person1.name.equals(person2.name);
    }
};

UnifiedSetWithHashingStrategy<Person> people = 
    UnifiedSetWithHashingStrategy.newSet(uniqueNameStrategy);

people.add(new Person("John", "New York", "Accountant"));
people.add(new Person("Bill", "London", "Manager"));
people.add(new Person("John", "New York", "Driver"));

people.each(person -> System.out.println(person.name + "/" + person.position));
//    Bill/Manager
//    John/Accountant

Note: I am a committer for Eclipse Collections .

itohro
  • 151
  • 5