Home > OS >  How can I remove the first instance of an object of a given class from an ArrayList in Java?
How can I remove the first instance of an object of a given class from an ArrayList in Java?

Time:11-03

I have an ArrayList<E>, where E has several subclasses. I want to remove the first instance of an object of subclass T.

My current implementation relies on an overridden equals(Object o) that looks at a constant that is unique to the subclass. Since objects of this subclass are interchangeable, I figured this would be much better than the usual implementations. See below.

public class E {
    //Stuff
}
public class T extends E {
    private static final String UNIQUE_STRING = "blah";
    //More variables
    public T() {
    }

    public static String getUniqueString() {
        return UNIQUE_STRING;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (this.getClass() == o.getClass()) {
            T t = (T) o;
            if (this.getUniqueString().equals(t.getUniqueString())) return true;
        }
        return false;
    }
    //Also has hashCode() here somewhere, as well as other methods
}
import java.util.List;
import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        initialize();
    }

    private static void initialize() {
        E t1 = new T();
        E t2 = new T();
        E t3 = new T();
        List<E> list = new ArrayList<>();
        list.add(t1);
        list.add(t2);
        list.add(t3);
        list.remove(new T());
    }
}

Using a Map<T, Integer> (or similar) is not feasible because list is going to contain other subclasses of E, not just T, and objects of those other subclasses differ in many respects. Only instances of T are, for all intents and purposes, interchangeable.

Separating instances of T from the list and using a Map<T, Integer> would be a major headache due to indexing and whatnot.

Finally, searching each object one by one until I found an instance of T (by using getClass() and the literal name of the class) seems like it'd be even worse.

My concern is that creating new objects to do this, while functional, is highly inefficient and potentially "dangerous". Is there a better way of achieving this?

CodePudding user response:

using instanceof is probably what you are looking for.

class Scratch {
    static class E {
        //Stuff
    }

    static class T extends E {

    }


    public static void main(String[] args) {
        final var arrayList = new ArrayList<>(List.of(new E(), new E(), new E(), new T(), new T(), new E()));
        for (E e : arrayList) {
            if (e instanceof T) {
                arrayList.remove(e);
                break;
            }
        }

        System.out.println(arrayList);
    }
}

[Scratch$E@5b1d2887, Scratch$E@46f5f779, Scratch$E@1c2c22f3, Scratch$T@18e8568, Scratch$E@33e5ccce]

This will continue to work work on subclasses of T as well.

CodePudding user response:

if you have an extensive list and you're looking for a faster way of doing things, you can use parallel streams of java 8

public static void main(String[] args) {
        final var arrayList = new ArrayList<>(List.of(new E(), new E(), new E(), new T(), new T(), new E()));
       var listWithoutTinstances = arrayList.parallelStream()
                .filter(e -> e instanceOf T)
                .collect(Collectors.toList());
    }

make sure you have to use parallel stream instead of simple one , you can check this to learn more: https://www.baeldung.com/java-when-to-use-parallel-stream

  • Related