0

I want to add unique objects into list on the basis of property of object.

class Employee {
    protected long   employeeId;
    protected String firstName;
    protected String lastName;

    Employee(long employeeId,String firstName,String lastName){
        this.employeeId = employeeId;
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

I want to insert object into list on the basis of unique 'employeeId' and 'firstName' , combination should be unique while inserting object into list.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
Qasim
  • 9,058
  • 8
  • 36
  • 50
  • Please add the code you use to add the instance to the list of `Employee`, and tell us which type is your list. – mins Mar 27 '15 at 07:00

3 Answers3

3

If you want certain containers to work that are able to prevent duplicates of your Employee from being added you need to define how equals is calculated in Employee.

public class Employee {
//...
    @Override
    public boolean equals(Object obj) {
       if (!(obj instanceof Person))
            return false;
        if (obj == this)
            return true;

        Person rhs = (Person) obj;
        return new EqualsBuilder()
            // if deriving: .appendSuper(super.equals(obj))
            .append(employeeId, rhs.employeeId)
            .append(firstName, rhs.firstName)
            .append(lastName, rhs.lastName)
            .isEquals();
    }
}

If you want certain containers to work that are able to look up your Employee quickly you need to define how hashcode is calculated in Employee.

public class Employee {
//...
    @Override
    public int hashCode() {
        int hash = 1;
        hash = hash * 17 + employeeId;
        hash = hash * 31 + firstName.hashCode();
        hash = hash * 13 + lastName.hashCode();
        return hash;
    }
}

Most modern IDE's will offer a re-factoring to do this for you. Use the same fields in both so they change together.

Since you don't want duplicates you're best bet is to not use ArrayList but something that pays attention to the hash and will enforce uniqueness for you. Whenever I'm picking a container in java I look at this:

enter image description here

To have all of those available to you, you need to implement not only hashcode and equals but comparator as well.

Just to be clear, the point of the hash is to provide lookup speed. The point of equals is to define what objects are considered identical. The point of comparator is to provide an ordering for the objects.

If you want to include the less frequently used containers try this:

enter image description here

Community
  • 1
  • 1
candied_orange
  • 7,036
  • 2
  • 28
  • 62
  • Much better - but you are still not talking about equals(). And as I said: these two methods should both be overwritten. – GhostCat Mar 27 '15 at 07:09
  • According to the java doc of `Set.add(E e)`: `adds the specified element e to this set if the set contains no element e2 such that (e==null ? e2==null : e.equals(e2)).` – Ian2thedv Mar 27 '15 at 07:23
  • Why is there no LinkedList here? Great graph though – Robin-Hoodie Mar 27 '15 at 07:26
  • @RobinHellemans You'll find your LinkedList in the bottom right corner – candied_orange Mar 27 '15 at 07:47
  • The first graph suggests `ArrayList` if you don't want duplicates, and you don't need to search the collection often? Sounds like nonsense to me. – Tom Mar 27 '15 at 07:57
  • Btw do you have the right to post the first image without any copyright information? – Tom Mar 27 '15 at 08:07
  • @Tom I believe we're supposed to understand that just because ArrayList isn't enforcing uniqueness doesn't mean it can't contain unique elements. It's suggesting ArrayList again if you don't need the searching/removing power the other 3 provide in favor of ArrayLists faster random access. – candied_orange Mar 27 '15 at 08:07
  • *"because ArrayList isn't enforcing uniqueness doesn't mean it can't contain unique elements."* Why should I use that collection type if I have to maintain the uniqueness myself? Where is the improvement of doing that and using `ArrayList` instead of using a `Set` in the first place? – Tom Mar 27 '15 at 08:09
  • @Tom Because in some use cases uniqueness is a non issue. Why check for it if it's never going to mater? – candied_orange Mar 27 '15 at 08:17
  • *"Why check for it if it's never going to mater?"* If it doesn't matter, then why should I answer the question *"Will it contain duplicates?"* with **no**? Does the creator of that graph think that the user has no idea what he _really_ wants? The second picture is better in that case. – Tom Mar 27 '15 at 08:21
  • @Tom Duplicates make all 3 sets inappropriate. Lack of duplicates does not nesisarily make ArrayList inappropriate. – candied_orange Mar 27 '15 at 08:23
  • *"Duplicates make all 3 sets inappropriate."* We are talking about _avoiding_ duplicates. *"Lack of duplicates does not nesisarily make ArrayList inappropriate."* And how do you know that there are no duplicates in the first place? Either because of some *implicit* knowledge about your program, or because you've checked that yourself. The first case highly couples your code to something that could change -> `ArrayList` would fail then. The second case requires your own checks. Why should I use a `List` then? – Tom Mar 27 '15 at 08:32
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/73910/discussion-between-candiedorange-and-tom). – candied_orange Mar 27 '15 at 08:34
  • Thanks for your reply @viswanathD but i want to know can we add objects into list . can u write code to add objects with no duplicates into list – Qasim Mar 27 '15 at 08:46
1

This can be achieved by overwriting the methods equals() and hashCode() - then you can turn to existing java.util collection classes (like HashSet) that use these methods when comparing objects.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
1

Here, equals() & hashCode() methods are overridden to meet the given requirements.

class Employee {
    protected long   employeeId;
    protected String firstName;
    protected String lastName;

    Employee(long employeeId,String firstName,String lastName){
        this.employeeId = employeeId;
        this.firstName = firstName;
        this.lastName = lastName;
    }

    public boolean equals(Object o){
        if(o == null) return false;
        if(!(o instanceof) Employee) return false;

        Employee other = (Employee) o;
        if(this.employeeId != other.employeeId)      return false;
        if(! this.firstName.equals(other.firstName)) return false;

        return true;
   }

    public int hashCode(){
        return (int) employeeId * firstName.hashCode();
    }
}

Here, if two Employee objects are equal, they will also have the same hash code. But, even still two Employee objects can be not equal having the same hash code.

Ex: The hash code is the employeeId is rounded down to an int. That means that many employee id's could result in the same hash code, but these Employee objects would still not be equal, since they don't have the same employee id.

Viswanath Donthi
  • 1,791
  • 1
  • 11
  • 12
  • Same here: It is bad style to only override equals() without overwriting equals(). And without telling Qasim that he should use a different data structure ... it would not work for him. And not providing any explanation - how is he supposed to learn from that? – GhostCat Mar 27 '15 at 07:05
  • @EddyG please check the complete solution. – Viswanath Donthi Mar 27 '15 at 07:07
  • @ViswanathD You are still missing to point out that he needs to use something else than a List .. – GhostCat Mar 27 '15 at 07:10
  • @ViswanathD You are still not mentioning at all that hashCode/equals are just "enabling" to use a data structure like HashSet. Just compare your answer the other two. – GhostCat Mar 27 '15 at 07:24