Java: Detect duplicates in ArrayList?

JavaArraysArraylistDuplicates

Java Problem Overview


How could I go about detecting (returning true/false) whether an ArrayList contains more than one of the same element in Java?

Many thanks, Terry

Edit Forgot to mention that I am not looking to compare "Blocks" with each other but their integer values. Each "block" has an int and this is what makes them different. I find the int of a particular Block by calling a method named "getNum" (e.g. table1[0][2].getNum();

Java Solutions


Solution 1 - Java

Simplest: dump the whole collection into a Set (using the Set(Collection) constructor or Set.addAll), then see if the Set has the same size as the ArrayList.

List<Integer> list = ...;
Set<Integer> set = new HashSet<Integer>(list);

if(set.size() < list.size()){
    /* There are duplicates */
}

Update: If I'm understanding your question correctly, you have a 2d array of Block, as in

Block table[][];

and you want to detect if any row of them has duplicates?

In that case, I could do the following, assuming that Block implements "equals" and "hashCode" correctly:

for (Block[] row : table) {
   Set set = new HashSet<Block>(); 
   for (Block cell : row) {
      set.add(cell);
   }
   if (set.size() < 6) { //has duplicate
   }
}

I'm not 100% sure of that for syntax, so it might be safer to write it as

for (int i = 0; i < 6; i++) {
   Set set = new HashSet<Block>(); 
   for (int j = 0; j < 6; j++)
    set.add(table[i][j]);
 ...

Set.add returns a boolean false if the item being added is already in the set, so you could even short circuit and bale out on any add that returns false if all you want to know is whether there are any duplicates.

Solution 2 - Java

Improved code, using return value of Set#add instead of comparing the size of list and set.

public static <T> boolean hasDuplicate(Iterable<T> all) {
    Set<T> set = new HashSet<T>();
    // Set#add returns false if the set does not change, which
    // indicates that a duplicate element has been added.
    for (T each: all) if (!set.add(each)) return true;
    return false;
}

Solution 3 - Java

With Java 8+ you can use Stream API:

boolean areAllDistinct(List<Block> blocksList) {
    return blocksList.stream().map(Block::getNum).distinct().count() == blockList.size();
}

Solution 4 - Java

If you are looking to avoid having duplicates at all, then you should just cut out the middle process of detecting duplicates and use a Set.

Solution 5 - Java

Improved code to return the duplicate elements

  • Can find duplicates in a Collection
  • return the set of duplicates
  • Unique Elements can be obtained from the Set

public static <T> List getDuplicate(Collection<T> list) {
 
    final List<T> duplicatedObjects = new ArrayList<T>();
    Set<T> set = new HashSet<T>() {
    @Override
    public boolean add(T e) {
        if (contains(e)) {
            duplicatedObjects.add(e);
        }
        return super.add(e);
    }
    };
   for (T t : list) {
        set.add(t);
    }
    return duplicatedObjects;
}


public static <T> boolean hasDuplicate(Collection<T> list) {
    if (getDuplicate(list).isEmpty())
        return false;
    return true;
}

Solution 6 - Java

I needed to do a similar operation for a Stream, but couldn't find a good example. Here's what I came up with.

public static <T> boolean areUnique(final Stream<T> stream) {
    final Set<T> seen = new HashSet<>();
    return stream.allMatch(seen::add);
}

This has the advantage of short-circuiting when duplicates are found early rather than having to process the whole stream and isn't much more complicated than just putting everything in a Set and checking the size. So this case would roughly be:

List<T> list = ...
boolean allDistinct = areUnique(list.stream());

Solution 7 - Java

If your elements are somehow Comparable (the fact that the order has any real meaning is indifferent -- it just needs to be consistent with your definition of equality), the fastest duplicate removal solution is going to sort the list ( 0(n log(n)) ) then to do a single pass and look for repeated elements (that is, equal elements that follow each other) (this is O(n)).

The overall complexity is going to be O(n log(n)), which is roughly the same as what you would get with a Set (n times long(n)), but with a much smaller constant. This is because the constant in sort/dedup results from the cost of comparing elements, whereas the cost from the set is most likely to result from a hash computation, plus one (possibly several) hash comparisons. If you are using a hash-based Set implementation, that is, because a Tree based is going to give you a O( n log²(n) ), which is even worse.

As I understand it, however, you do not need to remove duplicates, but merely test for their existence. So you should hand-code a merge or heap sort algorithm on your array, that simply exits returning true (i.e. "there is a dup") if your comparator returns 0, and otherwise completes the sort, and traverse the sorted array testing for repeats. In a merge or heap sort, indeed, when the sort is completed, you will have compared every duplicate pair unless both elements were already in their final positions (which is unlikely). Thus, a tweaked sort algorithm should yield a huge performance improvement (I would have to prove that, but I guess the tweaked algorithm should be in the O(log(n)) on uniformly random data)

Solution 8 - Java

If you want the set of duplicate values:

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class FindDuplicateInArrayList {

	public static void main(String[] args) {

		Set<String> uniqueSet = new HashSet<String>();
		List<String> dupesList = new ArrayList<String>();
		for (String a : args) {
			if (uniqueSet.contains(a))
				dupesList.add(a);
			else
				uniqueSet.add(a);
		}
		System.out.println(uniqueSet.size() + " distinct words: " + uniqueSet);
		System.out.println(dupesList.size() + " dupesList words: " + dupesList);
	}
}

And probably also think about trimming values or using lowercase ... depending on your case.

Solution 9 - Java

Simply put:

  1. make sure all items are comparable
  2. sort the array
  3. iterate over the array and find duplicates

Solution 10 - Java

To know the Duplicates in a List use the following code:It will give you the set which contains duplicates.

 public Set<?> findDuplicatesInList(List<?> beanList) {
	System.out.println("findDuplicatesInList::"+beanList);
	Set<Object> duplicateRowSet=null;
	duplicateRowSet=new LinkedHashSet<Object>();
			for(int	i=0;i<beanList.size();i++){
				Object superString=beanList.get(i);
				System.out.println("findDuplicatesInList::superString::"+superString);
				for(int	j=0;j<beanList.size();j++){
					if(i!=j){
						 Object	subString=beanList.get(j);
						 System.out.println("findDuplicatesInList::subString::"+subString);
						 if(superString.equals(subString)){
							 duplicateRowSet.add(beanList.get(j));
						 }
					}
				}
			}
			System.out.println("findDuplicatesInList::duplicationSet::"+duplicateRowSet);
		return duplicateRowSet;
  }

Solution 11 - Java

best way to handle this issue is to use a HashSet :

ArrayList<String> listGroupCode = new ArrayList<>();
listGroupCode.add("A");
listGroupCode.add("A");
listGroupCode.add("B");
listGroupCode.add("C");
HashSet<String> set = new HashSet<>(listGroupCode);
ArrayList<String> result = new ArrayList<>(set);

Just print result arraylist and see the result without duplicates :)

Solution 12 - Java

This answer is wrriten in Kotlin, but can easily be translated to Java.

If your arraylist's size is within a fixed small range, then this is a great solution.

var duplicateDetected = false
    if(arrList.size > 1){
        for(i in 0 until arrList.size){
            for(j in 0 until arrList.size){
                if(i != j && arrList.get(i) == arrList.get(j)){
                    duplicateDetected = true
                }
            }
        }
    }

Solution 13 - Java

private boolean isDuplicate() {
    for (int i = 0; i < arrayList.size(); i++) {
        for (int j = i + 1; j < arrayList.size(); j++) {
            if (arrayList.get(i).getName().trim().equalsIgnoreCase(arrayList.get(j).getName().trim())) {
                return true;
            }
        }
    }

    return false;
}

Solution 14 - Java

	String tempVal = null;
	for (int i = 0; i < l.size(); i++) {
		tempVal = l.get(i); //take the ith object out of list
		while (l.contains(tempVal)) {
			l.remove(tempVal); //remove all matching entries
		}
		l.add(tempVal); //at last add one entry
	}

Note: this will have major performance hit though as items are removed from start of the list. To address this, we have two options. 1) iterate in reverse order and remove elements. 2) Use LinkedList instead of ArrayList. Due to biased questions asked in interviews to remove duplicates from List without using any other collection, above example is the answer. In real world though, if I have to achieve this, I will put elements from List to Set, simple!

Solution 15 - Java

/**
	 * Method to detect presence of duplicates in a generic list. 
	 * Depends on the equals method of the concrete type. make sure to override it as required.
	 */
	public static <T> boolean hasDuplicates(List<T> list){
		int count = list.size();
		T t1,t2;
		
		for(int i=0;i<count;i++){
			t1 = list.get(i);
			for(int j=i+1;j<count;j++){
				t2 = list.get(j);
				if(t2.equals(t1)){
					return true;
				}
			}
		}
		return false;
	}

An example of a concrete class that has overridden equals() :

public class Reminder{
	private long id;
	private int hour;
	private int minute;
	
	public Reminder(long id, int hour, int minute){
		this.id = id;
		this.hour = hour;
		this.minute = minute;
	}
		
	@Override
    public boolean equals(Object other){
		if(other == null) return false;
		if(this.getClass() != other.getClass()) return false;
		Reminder otherReminder = (Reminder) other;
		if(this.hour != otherReminder.hour) return false;
		if(this.minute != otherReminder.minute) return false;
		
		return true;
	}
}

Solution 16 - Java

    ArrayList<String> withDuplicates = new ArrayList<>();
    withDuplicates.add("1");
    withDuplicates.add("2");
    withDuplicates.add("1");
    withDuplicates.add("3");
    HashSet<String> set = new HashSet<>(withDuplicates);
    ArrayList<String> withoutDupicates = new ArrayList<>(set);
    
    ArrayList<String> duplicates = new ArrayList<String>();

    Iterator<String> dupIter = withDuplicates.iterator();
    while(dupIter.hasNext())
    {
    String dupWord = dupIter.next();
    if(withDuplicates.contains(dupWord))
    {
    	duplicates.add(dupWord);
    }else{
    	withoutDupicates.add(dupWord);
    }
    }
  System.out.println(duplicates);
  System.out.println(withoutDupicates);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTerryView Question on Stackoverflow
Solution 1 - JavaPaul TomblinView Answer on Stackoverflow
Solution 2 - JavaakuhnView Answer on Stackoverflow
Solution 3 - JavaSergiy DakhniyView Answer on Stackoverflow
Solution 4 - Javamatt bView Answer on Stackoverflow
Solution 5 - Javauser60062View Answer on Stackoverflow
Solution 6 - JavaJay AndersonView Answer on Stackoverflow
Solution 7 - JavaVarkhanView Answer on Stackoverflow
Solution 8 - JavaSaurabhView Answer on Stackoverflow
Solution 9 - JavaAntonioView Answer on Stackoverflow
Solution 10 - JavaRakesh SabbaniView Answer on Stackoverflow
Solution 11 - JavaAshana.JackolView Answer on Stackoverflow
Solution 12 - JavagrantespoView Answer on Stackoverflow
Solution 13 - JavaKetan RamaniView Answer on Stackoverflow
Solution 14 - JavaAmitesh JhaView Answer on Stackoverflow
Solution 15 - JavafaizalView Answer on Stackoverflow
Solution 16 - JavaVenkataView Answer on Stackoverflow