2

Please, before downvote - read the question and check the example - this is not duplicate!

I want to remove every duplicated element from ArrayList in Java, like this:

Original list: [4, 2, 2, 3, 4, 1]
Set result: [1, 2, 3, 4]
Desired result: [1, 3]

The obvious solution for duplicates - set does not work here.

My solution:

        ArrayList<Integer> arrayList = new ArrayList<Integer>();
        arrayList.add(5);
        arrayList.add(1);
        arrayList.add(5);
        arrayList.add(1);
        arrayList.add(5);
        arrayList.add(2);
        arrayList.add(3);

        ArrayList<Integer> temp = new ArrayList<>(arrayList);

        for(Integer number : new HashSet<Integer>(arrayList)){
            temp.remove(number);
        }

        arrayList.removeAll(temp);

Any smarter/more clever solutions?

12
  • 3
    The duplicate provided wasn't correct, but you still haven't shown any effort. Commented Jul 28, 2014 at 15:22
  • Duplicate of what? Anyway what is your question and problem you are facing? I can see what you want to achieve but I don't see part which you explain what stops you from doing it. Commented Jul 28, 2014 at 15:22
  • I've asked this question 2 min ago and got 6 downvotes for duplicate question, but it's clearly not. Commented Jul 28, 2014 at 15:23
  • 5
    @mickey Your links are not correct. Check "Desired result", not "Set result". Commented Jul 28, 2014 at 15:26
  • 3
    Since you already have a working solution and you are interested in improving it (I assume it doesn't have bugs) you should post your question on codereview.stackexchange.com. General rule is (1) if your code works but you'd love to hear how it could work better post on Code Review (2) if you are trying to get your code to work post on Stack Overflow. Anyway since you already posted your question on Stack Overflow this advice is for your future questions (you should post question only on one of StackExchange sites so choose either SO or CR, never post same question both sites). Commented Jul 28, 2014 at 16:00

3 Answers 3

3

There are many ways to do what you are looking to do. Here is one (where T is the type stored by your existing List):

  1. Allocate a Map<T, Integer>. The integer will be used to store the number of times that item appears in your list.
  2. Iterate over your list. Look up each item in the map. If it doesn't exist, put back a count of one. If it does already exist in the map, increment the count and put back the new count.
  3. Iterate over the Entry's in the map to extract your de-duplicated list. You will not include any Entry with a value that is greater than one.

This approach will be fast even for large lists.

Sign up to request clarification or add additional context in comments.

1 Comment

Nice. I don't even need counter. Simple true/false is enough :)
2

Alternatively you can check for frequency as remove as well. Collections.frequency(arrayList, number)

public static void main(String[] args) {
    ArrayList<Integer> arrayList = new ArrayList<Integer>();
    arrayList.add(5);
    arrayList.add(1);
    arrayList.add(5);
    arrayList.add(1);
    arrayList.add(5);
    arrayList.add(2);
    arrayList.add(3);

    ArrayList<Integer> unique = new ArrayList<>();

    for (Integer number : arrayList) {
        if (Collections.frequency(arrayList, number) == 1) {
            unique.add(number);
        }
    }

    System.out.println(unique);
}

2 Comments

You could also change the frequency condition to == 1 and then use the resultant list as the list of those numbers not repeated.
Yes. Good idea. That will void an additional looping. Updated my answer.. :)
1

You can use a loop to check for duplicates in an ArrayList, and then use remove() on the ArrayList to remove the elements.

Please see the following:

{
    ArrayList list;
    // ...
    while(true)
        for(final Integer o : list) {
            if(list.indexOf(o) != list.lastIndexOf(o)) {
                while(list.remove(o));
                continue;
            }
            break;
        }
}

Alternatively a better approach would be to use a temporary Set to store the objects to remove:

{
    ArrayList list;
    TreeSet<Integer> set = new TreeSet<>(); // Use your Set!
    // ...
    for(final Integer o : list)
        if(list.indexOf(o) != list.lastIndexOf(o))
            set.add(o);
    for(final Integer o : set)
        while(list.remove(o));
}

4 Comments

I think it's better to simply copy the list - iterate over one and remove from another :)
You shouldn't modify collection which you are iterating with for-each loop.
@Pshemo I've fixed it. Please note that Iterable used in for-each loops concurrently calls .next() until .hasNext() returns false, therefore you need to restart the iteration after each modification (continue -> redo while(true) block -> for-each again).
FYI, added solution for use of a temporary Set.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.