Deleting duplicate elements in an ArrayList Java

Hi and thanks for reading! I'm currently studying Generics in Java and this is what I'm trying to accomplish:

I need to delete duplicate elements from an ArrayList. Currently, the ArrayList contains integers. I want to first print the original list, and then print the resulting list after removing the duplicates. This is what I have so far. Any help is appreciated!

public static void main(String[] args) {
    ArrayList<Integer> list1 = new ArrayList<Integer>();

    list1.add(1);
    list1.add(1);
    list1.add(1);

    list1.add(2);
    list1.add(2);
    list1.add(2);

    list1.add(3);
    list1.add(3);
    list1.add(3);

    removeDuplicates(list1);

      System.out.println("Original List with Duplicates: \n" + list1);
        System.out.println();
        //System.out.println("After removing duplicates: \n" + list2);

}

public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list2){


    for(int i = 0; i < list2.size(); i++){

    //logic to remove duplicates    


    }

    return list2;
}   

Answers


You could add the elements to the Set collection. If you want to preserve order you should use LinkedHashSet


Step One

Convert your list to a set.

Set<Integer> aSet = new HashSet<Integer>(list);

Step Two

Convert your set back to a list.

list = new ArrayList<Integer>(new HashSet<Integer>(list));

Why it Works

Sets can only contain unique elements.


public static void main(String[] args) {
    ArrayList<Integer> list1 = new ArrayList<Integer>();
    ArrayList<Integer> list2 = new ArrayList<Integer>();

    list1.add(1);
    list1.add(1);
    list1.add(1);

    list1.add(2);
    list1.add(2);
    list1.add(2);

    list1.add(3);
    list1.add(3);
    list1.add(3);



      System.out.println("Original List with Duplicates: \n" + list1);
      System.out.println();

      list2 = removeDuplicates(list1);

      System.out.println("After removing duplicates: \n" + list2);

}

public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list2){

    ArrayList<E> usedList = new ArrayList<E>();
    ArrayList<E> newList = new ArrayList<E>();

    for(int i = 0; i < list2.size(); i++){

        E object = list2.get(i);

        if(! usedList.contains(object))
        {
            usedList.add(object);
            newList.add(object);
        }
    }

    return newList;
} 

Output (as expected):

Original List with Duplicates: 
[1, 1, 1, 2, 2, 2, 3, 3, 3]

After removing duplicates: 
[1, 2, 3]

If you're working with other types (not java standard like int), then you have to override the equals method, because it's used in the ArrayList contains method.


public static <E> ArrayList<E> removeDuplicates(ArrayList<E> list2){
    LinkedHashSet<E> dataSet = new LinkedHashSet<E>(list2.size());
    dataSet.addAll(list2);
    ArrayList<E> uniqueLists = new ArrayList<E>(dataSet.size());
    uniqueLists.addAll(dataSet);
    return uniqueLists;
}

Convert the ArrayList to Set, maybe HashSet and then back to an ArrayList that you could sort if you want the numbers in order (the ordering in Sets are not usually not guaranteed).

HashSet hs<Integer> = new HashSet(list1);

ArrayList<Integer> uniqueList = Collections.sort(new ArrayList<Integer>(hs));

There's also various SortedSet, among them TreeSet.

Also, you can use a less error-prone for loop construction:

for (int i : uniqueList) {
   System.out.println(i);
}

All the other answers so far create a new list. If you want to modify the list in place, you can iterate through the list while using an auxiliary Set to keep track of all elements already seen. The following works for any List (not just ArrayList) that allows elements to be removed:

public static <E> List<E> removeDuplicates(List<E> list){
    ListIterator<E> iter = list.listIterator();
    Set<E> seen = new HashSet<>();
    while (iter.hasNext()) {
        if (!seen.add(iter.next())) {
            // element not added--must have already been seen, so remove element
            iter.remove();
        }
    }
    return list;
}

An alternative is to dump the entire list into a Set, clear the list, and then add all the element of the set back into the list. Depending on the Set implementation, this may or may not preserve order.

public static <E> List<E> removeDuplicates(List<E> list){
    Set<E> unique = new LinkedHashSet<>(list);
    list.clear();
    list.addAll(unique);
    return list;
}

EDIT: If (as per your comment) you wish to completely remove elements that are not unique to start with, you can modify the first approach:

public static <E> List<E> removeNonUnique(List<E> list){
    Set<E> seen = new HashSet<>(); // all values seen
    Set<E> dups = new HashSet<>(); // all values seen more than once
    for (E elt : list) {
        if (!seen.add(elt)) {
            // element not added--must have already been seen, so add to dups
            dups.add(elt);
        }
    }
    // clean out the list
    list.removeAll(dups);
    return list;
}

Note that since we're not modifying the list during the loop, we don't need to have an explicit iterator.


Need Your Help

How to access the subdomain of an IP address in the browser?

firefox browser web ip ip-address

To get to the IP address of an example website, you just visit

Prevent div from stretching its background-image

html css background-image

I have a div with a background-image defined as follows in my stylesheet: