I have an ArrayList of custom objects. I want to remove duplicate entries.

The objects have three fields: title, subtitle, and id. If a subtitle occurs multiple times, I only need the first item with thats subtitle (ignore the remaining object with that subtitle).

  • 2
    If you don't want duplicates, using a Set in the first place would be simpler. – Peter Lawrey Apr 21 '11 at 8:12
  • i have use tree set and add the subtitle in tree if the add method return true i add the object in another arraylist – Bytecode Apr 21 '11 at 12:19

14 Answers 14


You can put the content of the ArrayList in a TreeSet using a custom Comparator which should return 0 if the two subtitles are the same. After that you can convert the Set in a List and have the List without "duplicates". Here is an example for Object, of course you should use the correct class and logic.

public void removeDuplicates(List<Object> l) {
    // ... the list is already populated
    Set<Object> s = new TreeSet<Object>(new Comparator<Object>() {

        public int compare(Object o1, Object o2) {
            // ... compare the two object according to your requirements
            return 0;
    List<Object> res = Arrays.asList(s.toArray());
  • I think overriding equals() (and hashCode()) as suggested on several answers below is a better solution, and moreover, your "removeDuplicates(...)" method doesn't remove duplicates from the "l" list : it doesn't even use "l". – Tristan Apr 21 '11 at 10:29
  • 2
    you're right, I forgot a line, the code is correct now. As for overriding equals and hashset I disagree as a general solution; overriding them is much more invasive than my solution, which would work even if you can't modify the original class. My 2c anyway, I accept the -1 for posting wrong code; I'm always open for critics – Riccardo Cossu Apr 21 '11 at 10:35
  • But it's a good practice to override equals and hashcode to make business unicity more explicit : community.jboss.org/wiki/EqualsandHashCode – Tristan Apr 21 '11 at 10:42
  • 1
    of course, if the order I want si ok as a natural (universal) order and I can modify the original classes I would definitely go for equals, hasCode or better even implement Comparable. But I have seen business requirements where I had to order objects in a different order than the natual one, and using a Comparator always works even if the previous conditions are not met. In general there is no best approach here, it depends on the scenario. – Riccardo Cossu Apr 21 '11 at 10:49
  • 1
    This works, but is really inefficient for both CPU and memory, as it allocates giant amount of memory, and since it's a TreeSet, it's not localized (= high CPU cache miss rate). See below for my solution that arranges this in-place. – Agoston Horvath Aug 28 '15 at 11:41
List list = (...);

//list may contain duplicates.

//remove duplicates if any
Set setItems = new LinkedHashSet(list);

You may need to override "equals()" so that 2 elements are considered equals if they have the same subtitle (or tite and subtitle maybe ?)

  • ... but does not work if the object has a member which is used for sorting, as the hash is different even if the key is the same (if other fields differ). – chksr Mar 18 '17 at 20:39

I would suggest using a Set


Which by its nature cannot contain duplicate items. You can create a new set from your original ArrayList using

Set myset = new HashSet(myArrayList);

Alternatively, just use a Set from the start, and don't use an ArrayList as it is not performing the function that you require.

  • One should NOT rely on equals and hashcode in this case, since the example is only looking for equality on one property. Instead create a new list with the wanted result. – crunchdog Apr 21 '11 at 7:48
  • 3
    If that one property is what marks the object as unique, why should he not override equals so that it only checks that one property? – Kevin D Apr 21 '11 at 7:58
  • Yes, if using equals is great (f.e. in some Frameworks datasets) and you want to unify your ArrayList you can do it with: myArrayList = new ArrayList(new HashSet(myArrayList)); But this is heavy work and you should do it just if you have to rely on lists in future Code (like Collections.shuffle()) – r00tandy Aug 27 '16 at 11:20
List<Item> result = new ArrayList<Item>();
Set<String> titles = new HashSet<String>();

for(Item item : originalList) {
    if(titles.add(item.getTitle()) {

add() of the Set returns false if the element already exists.

  • You are best :) It is better than Riccardo Cossu – user3402040 Jun 12 '15 at 8:35

If I understand correctly you have an ArrayList<Custom>, let's call it list. Your Custom class has a subtitle field, let's say with a getSubtitle() method that returns String. You want to keep only the first unique subtitle and remove any remaining duplicates. Here's how you can do that:

Set<String> subtitles = new HashSet<String>();
for (Iterator<Custom> it = list.iterator(); it.hasNext(); ) {
    if (!subtitles.add(it.next().getSubtitle())) {

You can use an O(n^2) solution: Use list.iterator() to iterate the list once, and on each iteration, iterate it again to check if there are duplicates. If there are - call iterator.remove(). A variation of this is to use guava's Iterables.filter(list, predicate) where your filtering logic is in the predicate.

Another way (perhaps better) would be to define the equals(..) and hashCode(..) methods to handle your custom equality logic, and then simply construct a new HashSet(list). This will clear duplicates.


Removes any duplicates in a collection, while preserving the order if it is an ordered collection. Efficient enough for most cases.

public static <I, T extends Collection<I>> T removeDuplicates(T collection)
    Set<I> setItems = new LinkedHashSet<I>(collection);

    return collection;

Update for Java8:

Using Java8 streams you can also do pretty trivally.

ArrayList<String> deduped;
deduped = yourArrayList.stream()

This also has the advantage over going ArrayListSetArrayList of maintaining ordering.


Use Collections.sort() to sort and use a simple for cycle to catch doubles, e.g.:

A previous = null;
for (A elem: myList) {
    if (elem.compareTo(previous) == 0) continue;
    previous = elem;

    [... process unique element ...]

This presumes that you'll implement Comparable in your type A.

  • more efficient but less flexible; it's probably better for large input sets – Riccardo Cossu Aug 28 '15 at 14:14
private static List<Integer> removeDuplicates(List<Integer> list) {
    ArrayList<Integer> uniqueList = new ArrayList<Integer>();
    for (Integer i : list) {
        if (!inArray(i, uniqueList)) {

    return uniqueList;

private static boolean inArray(Integer i, List<Integer> list) {
    for (Integer integer : list) {
        if (integer == i) {
            return true;

    return false;
  • Your solution works only with a list of Integers. The OP specifically said the list contains custom objects. – Laf Aug 6 '13 at 19:46
  • well .. substitute integer for those objects and change the condition in ´inArray´ ... – urSus Aug 7 '13 at 2:02

The solution depends on circumstances.

If you don't have much data then go with a Set Set<T> unique = new HashSet<>(yourList); (use LinkedHashSet if you care about the order. It creates a new collection, but usually it's not a problem.

When you want to modify existing list and don't want to/can't create a new collection, you can remove duplicates like here:

List<Integer> numbers =
    new ArrayList<>(asList(1, 1, 2, 1, 2, 3, 5));

System.out.println("Numbers: " + numbers);
ListIterator<Integer> it = numbers.listIterator();
while (it.hasNext()) {
    int i = it.nextIndex();
    Integer current = it.next();
        if (current.equals(numbers.get(j))) {
System.out.println("Unique: " + numbers);

It works in O(n^2), but it works. Similar implementation, but simpler, is when the list is sorted - works in O(n) time. Both implementations are explained at Farenda: remove duplicates from list - various implementations.


In Java 8, you can also do something like this:

         obj -> obj.getSubtitle(),
         (o1,o2) -> o1))

The trick is to collect stream to map and provide key collision resolver lambda ((o1,o2) -> o1) which always returns its first parameter. The result is a Collection, not a List but you can easily convert it to a List:

new ArrayList(resultCollection);
List<YourObject> all = ******** // this is the object that you have already  and filled it.
List<YourObject> noRepeat= new ArrayList<YourObject>();

for (YourObject al: all) {
    boolean isPresent = false;
    // check if the current objects subtitle already exists in noRepeat
    for (YourObject nr : noRepeat) {
        if (nr.getName().equals(al.getName()) {
            isFound = true;//yes we have already

    if (!isPresent)
        noRepeat.add(al); // we are adding if we don't have already

take one new ArrayList Object of same type
one by one add all the old arraylists elements into this new arraylist object but before adding every object check in the new arraylist that if there is any object with the same subtitle.if new arraylist contains such subtitle don't add it. otherwise add it


Another method using Java 8 streams you can also do pretty cool:

List<Customer> CustomerLists;
List<Customer> unique = CustomerLists.stream().collect(collectingAndThen(
        toCollection(() -> new TreeSet<>(comparingLong(Customer::getId))),

Your Answer

