Выяснить, содержит ли список объектов что-то с указанным значением поля?

у меня есть список DTO, полученный от БД, и у них есть идентификатор. Я хочу убедиться, что мой список содержит объект с указанным ID. По-видимому, создание объекта с ожидаемыми полями в этом случае не поможет, потому что contains () вызывает Object.Equals(), и они не будут равны.

Я подошел к решению так: создал интерфейс HasId, реализовал его во всех моих DTOs и унаследовал ArrayList с новым классом, который имеет contains(Long id) метод.

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;
    }
}

но в этом случае я не могу напечатать список и ArrayList в SearchableList... Я бы с этим смирился, но хотел убедиться, что не изобрету велосипед.

EDIT (Oct ' 16):

конечно, с введением lambdas в Java 8 способ сделать это прост:

list.stream().anyMatch(dto -> dto.getId() == id);

6 ответов


Я предлагаю создать простой статический метод, как вы написали, без каких-либо дополнительных интерфейсов:

public static boolean containsId(List<DTO> list, long id) {
    for (DTO object : list) {
        if (object.getId() == id) {
            return true;
        }
    }
    return false;
}

Я предлагаю вам просто переопределить equals в своем SearchableDto это было бы что-то вроде:

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

в этом случае contains должно работать, вероятно, если он имеет то же самое id;


Ну, я думаю, что ваш подход немного усложнять проблему. Ты сказал:

у меня есть список DTO, полученный от БД, и у них есть идентификатор.

тогда, вероятно, вам следует использовать класс DTO для хранения этих элементов. Если это так, поместите ID getter и setter внутри этого класса:

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

этого достаточно для перебора и ArrayList и поиска нужного идентификатора. Расширение класса ArrayList только для добавления feautre "compare-id" кажется я слишком запутался. @Nikita Beloglazov - хороший пример. Вы можете обобщить его еще больше:

public boolean containsId(List<HasId> list, long id) {
    for (HasId object : list) {
        if (object.getId() == id) {
            return true;
        }
    }
    return false;
}

вы требование не ясно для меня. Когда вы говорите: "убедитесь, что мой список содержит объект с указанным идентификатором", вы хотите:

  1. обнаружить, если ID присутствует и действовать соответственно
  2. всегда включайте DTO с требуемым идентификатором в результаты

большинство ответов предполагали, что вы имеете в виду 1, однако, думая об этом, вы могли бы также означать 2, учитывая формулировку вопроса. Вы можете включить требуемый результат, изменив ваш запрос:

SELECT * FROM employee WHERE firstname = 'John' OR id = 42;

   public boolean containsId(List<HasId> list, long id) {
    boolean flag = false;
    for (HasId object : list) {
        if (object.getId() == id) {
           flag = true;
        }
    }
    return flag;
}

это то, что я использовал в своей функции DFS GetUnvisitedNeighbour.

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

Я работал в C#. Лямбда-выражения в C# намного проще работать, чем в Java.

можно использовать filter функция для добавления условия для свойства элемента.

затем использовать findFirst().get() или findAny.get() согласно вашей логике.