1

I have 2 ArrayList of custom objects. I want to remove duplicate entries from both the ArrayList.

The objects have three fields: fName, lName, and id. If the id occurs multiple times, I want to remove from both the lists.

How can I do that?

I am fine with merging both the lists and removing the 2 duplicate entries as well.

4 Answers 4

2

If you want to merge: simply copy the content of both lists to a map. Then you don't have the duplicates anymore (but you loose your actual ordering):

Map<Integer, MyObject> temp = new HashMap<Integer, MyObject>();
for (MyObject obj:firstList) {
   temp.put(obj.getId(), obj);
}
for (MyObject obj:secondList) {
   temp.put(obj.getId(), obj);
}
List<MyObject> result = new ArrayList<MyObject>(temp.values());
Sign up to request clarification or add additional context in comments.

2 Comments

He wants to remove duplicates from both lists, not just uniqify the combined lists.
Mergeing was OK for him - but I didn't pay attention, objects are "duplicates" if they only have the same id. So map is a better approach
1

If your classes have a correct implementation of the equals and hashCode method, turn the list into a HashSet to eliminate the duplicates. The HashSet<T> constructor accepts a Collection<T> so you should be good to go.

If you need some custom comparator function (like the one in your case which compares only id), pass in a custom Comparator<T> implementation when creating the TreeSet. To sum it up, just create a comparator which compares ids of both the objects and pass it to the TreeSet constructor. Then adding items from both the lists to this set will take care of eliminating the duplicates. Something like:

public class Test {

    public static void main(String[] args) {
        Person p1 = new Person("first", "id1");
        Person p2 = new Person("dummy", "id1"); // same id as above
        Person p3 = new Person("second", "id2");
        Person p4 = new Person("third", "id1");
        List<Person> asList = Arrays.asList(p1, p2, p3, p4);
        CustomComparator comparator = new CustomComparator();
        TreeSet<Person> ts = new TreeSet<Person>(comparator);
        TreeSet<Person> duplicates = new TreeSet<Person>(comparator);
        for (Person p : asList) {
            if (ts.contains(p) || duplicates.contains(p)) {
                duplicates.add(p);
                ts.remove(p);
            } else {
                ts.add(p);
            }
        }
        System.out.println(ts);
    }

}

class Person {

    public Person(String name, String id) {
        super();
        this.name = name;
        this.id = id;
    }

    public String name;

    public String id;

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("Person [id=");
        builder.append(id);
        builder.append(", name=");
        builder.append(name);
        builder.append("]");
        return builder.toString();
    }

}

class CustomComparator implements Comparator<Person> {

    @Override
    public int compare(Person o1, Person o2) {
        return o1.id.compareTo(o2.id);
    }

}

4 Comments

Actually I am already overriding equals() for removing duplicates based on the field fName.. (i.e. use removeAll to remove common fName from one of the lists)...But in case of "id" field, I want to remove from both the lists. So not sure how I can acheive this ?
I've added a sample snippet for illustration purposes.
I just tried the example u gave...It removes one of the duplicate objects...I want to remove both the duplicates...i.e. as per your example, in the end, it should return just 1 record (id2)...
I've updated the code, have a look. Not the best implementation I must agree but works. Can be tuned if you find performance issues.
0

Use Set for this purpose.

Note: Great care must be exercised if mutable objects are used as set elements. The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set. A special case of this prohibition is that it is not permissible for a set to contain itself as an element.

Comments

0
HashSet<Integer> list_1_ids = new HashSet<Integer>();
HashSet<Integer> list_2_ids = new HashSet<Integer>();
for (CustomObject x : list1) list_1_ids.add(x.id);
for (CustomObject x : list2) list_2_ids.add(x.id);
HashSet<Integer> both_ids = list_1_ids;
both_ids.retainAll(list_2_ids);
List<CustomObject> pruned_list_1 = new ArrayList<CustomObject>();
for (CustomObject x : list1) if (!both_ids.contains(x.id)) pruned_list_1.add(x);
List<CustomObject> pruned_list_2 = new ArrayList<CustomObject>();
for (CustomObject x : list2) if (!both_ids.contains(x.id)) pruned_list_2.add(x);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.