2011-09-20 15 views
25

Mam listę DTO otrzymanych z DB i mają identyfikator. Chcę się upewnić, że moja lista zawiera obiekt o określonym ID. Wygląda na to, że tworzenie obiektu z oczekiwanymi polami w tym przypadku nie pomoże, ponieważ wywołuje() wywołania Object.equals() i nie będą one równe.Sprawdzanie, czy lista obiektów zawiera coś z określoną wartością pola?

Podszedłem do rozwiązania takiego jak: stworzyłem interfejs HasId, zaimplementowałem go we wszystkich moich DTO i odziedziczyłem ArrayList nową klasą, która ma metodę 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; 
    } 
} 

Ale w tym przypadku nie mogę typecast Lista i ArrayList do SearchableList ... bym z tym żyć, ale chciałem się upewnić, że nie jestem wynalezienie roweru.

EDIT (październik '16):

Oczywiście, wraz z wprowadzeniem lambda w Java 8 Sposobem na to jest prosta:

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

Jestem pewien, że chodziło Ci o "Wymyślanie koła". – Nishan

+0

dlaczego nie po prostu przeszukać listę ? –

+0

Nishan, dokładnie to miałem na myśli, to był problem z tłumaczeniem: D Ray Tayek, łał, taki prosty i elegancki pomysł nawet mi nie przyszedł, upewnię się, że go wypróbuję, dziękuję – Sergey

Odpowiedz

44

Proponuję utworzyć prostą metodę statyczną jak ty napisał, bez żadnych dodatkowych interfejsów:

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

Dla lepszej czytelności kodu chciałbym usunąć nawiasy z dla i jeśli. To jest dobra praktyka w mojej opinii. W każdym razie dzięki za tę metodę! – wzieba

+0

hmm, nie najlepsza opcja pod względem wydajności, myślę, że rozwiązanie @ medopal jest lepsze – Choletski

+1

@Choletski co jest nie tak z wydajnością tutaj? Nie można zrobić lepiej niż O (N), zakładając, że nie używamy obliczeń równoległych. –

2

Cóż, myślę, że twoje podejście trochę komplikuje problem. Powiedziałeś:

Mam listę DTO otrzymanych z DB i mają identyfikator.

Prawdopodobnie powinieneś użyć klasy DTO do przechowywania tych przedmiotów. Jeśli więc umieścić id getter i setter wewnątrz tej klasy:

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

to wystarczy na iterację i ArrayList i wyszukać żądaną id. Rozszerzenie klasy ArrayList tylko w celu dodania feautre "porównania identyfikatora" wydaje się zbyt skomplikowane. @Nikita Beloglazov są dobrym przykładem. Można uogólnić, że nawet bardziej:

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

Proponuję po prostu zastąpić equals w swoim SearchableDto byłoby coś takiego:

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

W tym przypadku contains powinien pracować prawdopodobnie jeśli jest to ten sam id ;

0

Twoje wymagania nie są dla mnie jasne. Kiedy mówisz „upewnić się, że moja lista zawiera obiekt o określonym ID” chcesz:

  1. wykryć, czy identyfikator jest obecny i działa odpowiednio
  2. zawsze zawierać dto z wymaganym ID w wynikach

Większość odpowiedzi zakładała, że ​​masz na myśli 1, jednak myśląc o tym, możesz równie dobrze znaczyć 2, biorąc pod uwagę sformułowanie pytania.Można to pożądanego rezultatu, zmieniając zapytanie:

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

To było oświadczenie testowe, chciałem się upewnić, że mój kod Hibernacji prawidłowo wykonał mapowanie i wyodrębnił prawidłowe wartości z bazy danych. – Sergey

+0

Cóż, jeśli jest to konkretny przypadek testowy, to dlaczego nie po prostu zapętlić nad pobranymi obiektami i nie wykonać testu, jeśli żądany identyfikator nie zostanie odnaleziony? Dlaczego miałbyś mieć wszystkie swoje DTO zaimplementować interfejs HasId właśnie do tego? –

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

lepiej przerwać pętlę 'for each', gdy wartość flagi ma wartość true zamiast pętli do końca –

0

To właśnie użyłem w mojej funkcji DFS GetUnvisitedNeighbour.

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

Kiedyś pracowałem w C#. Wyrażenia Lambda w języku C# są znacznie łatwiejsze w użyciu niż w Javie.

Możesz użyć funkcji filter, aby dodać warunek dla właściwości elementu.

Następnie użyj findFirst().get() lub findAny.get() według swojej logiki.

Powiązane problemy