Finding out if a list of Objects contains something with a specified field value?
Asked Answered
G

6

30

I have a list of DTO received from a DB, and they have an ID. I want to ensure that my list contains an object with a specified ID. Apparently creating an object with expected fields in this case won't help because contains() calls for Object.equals(), and they won't be equal.

I came up to a solution like so: created an interface HasId, implemented it in all my DTOs, and inherited ArrayList with a new class that has contains(Long id) method.

public interface HasId {
    void setId(Long id);
    Long getId();
}

public class SearchableList<T extends HasId> extends ArrayList<T> {
    public boolean contains(Long id) {
        for (T o : this) {
            if (o.getId() == id)
                return true;
        }
        return false;
    }
}

But in this case I can't typecast List and ArrayList to SearchableList... I'd live with that, but wanted to make sure that I'm not inventing the wheel.

EDIT (Oct '16):

Of course, with the introduction of lambdas in Java 8 the way to do this is straightforward:

list.stream().anyMatch(dto -> dto.getId() == id);
Gout answered 20/9, 2011 at 7:7 Comment(5)
I am sure you meant 'Inventing the wheel'.Reld
why not just search a List<HasID>?Larrisa
Nishan, this is exactly what I meant, it was a translation issue :D Ray Tayek, wow, such a simple and elegant idea didn't even cross my mind, I'll make sure I'll try it out, thank youGout
Not sure if I can typecast List<DTO> to List<HasId> thoughGout
thank you for your edit with the anyMatch() method.Symbolist
S
51

I propose to create simple static method like you wrote, without any additional interfaces:

public static boolean containsId(List<DTO> list, long id) {
    for (DTO object : list) {
        if (object.getId() == id) {
            return true;
        }
    }
    return false;
}
Supraorbital answered 20/9, 2011 at 7:10 Comment(3)
For better code readability I would remove brackets from for and if. It's good practice in my opinion. Anyway thanks for this method!Exurb
hmm, not the best option in terms of performance, I think @medopal's solution is betterLacee
@Lacee what's wrong with performance here? You cannot do better than O(N) assuming that we don't use parallel computation.Supraorbital
F
8

I suggest you just override the equals in your SearchableDto it would be something like:

public boolean equals(Object o){
    if (o instanceof SearchableDto){
        SearchableDto temp = (SearchableDto)o;
        if (this.id.equals(temp.getId()))
            return true;
    }
    return false;
}

In this case contains should work probably if it has the same id;

Fryer answered 20/9, 2011 at 7:27 Comment(0)
M
2

Well, i think your approach is a bit overcomplicating the problem. You said:

I have a list of DTO received from a DB, and they have an ID.

Then probably you should use a DTO class to hold those items. If so put id getter and setter inside that class:

public class DTO implements HasId{
    void setId(Long id);
    Long getId();
}

That's enough for iterate through and ArrayList and search for the desired id. Extending ArrayList class only for adding the "compare-id" feautre seems overcomplicated o me. @Nikita Beloglazov make a good example. You can generalize it even more:

public boolean containsId(List<HasId> list, long id) {
    for (HasId object : list) {
        if (object.getId() == id) {
            return true;
        }
    }
    return false;
}
Mariejeanne answered 20/9, 2011 at 7:14 Comment(0)
I
1

This is what I used in my DFS GetUnvisitedNeighbour function.

    public static int GetUnvisitedNeighbour(int v)
{
    Vertex vertex = VertexList.stream().filter(c -> c.Data == v).findFirst().get();
    int position = VertexList.indexOf(vertex);
    ...
}

I used to work in C#. Lambda expressions in C# are much easier to work with than they are in Java.

You can use filter function to add condition for property of element.

Then use findFirst().get() or findAny.get() according to your logic.

Implied answered 28/7, 2017 at 14:8 Comment(0)
S
0

You requirement is not clear to me. When you say 'ensure that my list contains an object with a specified ID' do you want to:

  1. detect if the ID is present and act accordingly
  2. always include the DTO with the required ID in your results

Most responses have assumed you mean 1, however when thinking about it you could just as well mean 2 given the wording of the question. You could include the required result by altering your query:

SELECT * FROM employee WHERE firstname = 'John' OR id = 42;
Soapbox answered 20/9, 2011 at 9:5 Comment(2)
It was a test statement, I wanted to make sure that my Hibernate code did its mapping correctly and extracted right values from the database.Gout
Well if this is a specific test case then why not just loop over the retrieved objects and fail the test if the desired ID is not found? Why would you have all your DTO's implement the HasId interface just for this?Soapbox
N
0
   public boolean containsId(List<HasId> list, long id) {
    boolean flag = false;
    for (HasId object : list) {
        if (object.getId() == id) {
           flag = true;
        }
    }
    return flag;
}
Nitz answered 8/1, 2017 at 10:17 Comment(1)
better to break the for each loop once flag value is true instead of looping till endSainfoin

© 2022 - 2024 — McMap. All rights reserved.