Search code examples
javaarraylistfiltersublist

Multiple lists or list and getSublist() (Java)


I have an abstract class 'entity' and Objects (that extend 'entity') that implement different interfaces. I also have an ArrayList that contain all those different Objects.

Now if I need access to all entities that implement a certain interface (to use its methods), I use the following method (which returns a filtered list of 'entities' that implement interface 'IDirectFire'):

public ArrayList<IDirectFire> getDirectFireSublist() {//direct fire sublist
    ArrayList<IDirectFire> sublist = new ArrayList();
    entities.stream().filter((it) -> (it instanceof IDirectFire)).forEach((it) -> {
        sublist.add((IDirectFire) it);
    });
    return sublist;
}

Now to my question: Should I further work with this method or should I create a new ArrayList that exists besides 'entities' and that I would need to manually update every time 'entities' changes?

I need to update 'entities' a lot so I'm not sure if it's more efficient to store multiple sublists and update them all every time 'entities' changes or if I should keep using methods to filter 'entities' and apply methods to those sublists. Keep in mind that those sublists would also be used in a loop in other methods e.g.:

private void resetFirestatusIDF() {//reset firestatus (IDirectFire)
    getDirectFireSublist().stream().forEach((it) -> {
        it.dfHasFired(false);
    });}

Is this viable? Thanks in advance!


Solution

  • If all you need is to loop over a subset of your items, creating a new list is wasteful. Just return the filtered Stream.

    public Stream<IDirectFire> getDirectFire() {
        return entities.stream().filter((it) -> (it instanceof IDirectFire));
    }
    

    You could also use Guava and return a filtered Iterable instead:

    public Iterable<IDirectFire> getDirectFire() {
        return FluentIterable.from(entities).filter(IDirectFire.class);
    }
    

    Then, to loop over the items elswhere:

    private void resetFirestatusIDF() {
        getDirectFire().forEach((it) -> it.dfHasFired(false));
    }