2011-09-20 21 views
25

Tengo una lista de DTO recibida de un DB, y tienen una identificación. Quiero asegurarme de que mi lista contiene un objeto con una ID especificada. Aparentemente, crear un objeto con campos esperados en este caso no ayudará porque contiene() llamadas para Object.equals(), y no serán iguales.Averiguar si una lista de Objetos contiene algo con un valor de campo especificado?

Vine a una solución como esa: creé una interfaz HasId, la implementé en todos mis DTOs, y he heredado ArrayList con una nueva clase que tiene el método 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; 
    } 
} 

Pero en este caso no puedo encasillado de lista y ArrayList a SearchableList ... Viviría con eso, pero quería asegurarse de que no estoy inventando la bicicleta.

EDITAR (octubre '16):

Por supuesto, con la introducción de lambdas en Java 8 la manera de hacer esto es sencillo:

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

Estoy seguro de que quería decir 'Inventar la rueda'. – Nishan

+0

¿por qué no buscar una lista ? –

+0

Nishan, esto es exactamente lo que quise decir, era un problema de traducción: D Ray Tayek, wow, una idea tan simple y elegante ni siquiera se me pasó por la cabeza, me aseguraré de probarlo, gracias – Sergey

Respuesta

44

propongo crear método estático simple como usted escribió, sin ninguna interfaz adicional:

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

Para una mejor legibilidad del código, eliminaría los paréntesis de para y si. Es una buena práctica en mi opinión. De todas formas gracias por este método! – wzieba

+0

hmm, no es la mejor opción en términos de rendimiento, creo que la solución de @medopal es mejor – Choletski

+1

@Choletski ¿Qué hay de malo con el rendimiento aquí? No se puede hacer mejor que O (N) suponiendo que no usemos cálculos paralelos. –

2

Bueno, creo que su enfoque es un poco complicado el problema. Usted dijo:

Tengo una lista de DTO recibida de una base de datos, y tienen una identificación.

Entonces probablemente deba usar una clase DTO para guardar esos elementos. Si es así puesto getter y setter Identificación dentro de esa clase:

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

eso es suficiente para iterar y ArrayList y la búsqueda de la identificación deseada. La extensión de la clase ArrayList solo para agregar la feautre "compare-id" parece demasiado complicada para mí. @Nikita Beloglazov es un buen ejemplo. Se puede generalizar aún más:

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

sugiero que acaba de anular el equals en su SearchableDto sería algo así como:

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

En este caso contains debería funcionar, probablemente, si no tiene el mismo id ;

0

Su requisito no está claro para mí. Cuando se dice 'asegurarse de que mi lista contiene un objeto con un ID especificado' qué quiere:

  1. detectar si el identificador está presente y actuar en consecuencia
  2. siempre incluyen el DTO con la identificación requerida en sus resultados

La mayoría de las respuestas han asumido que significa 1, sin embargo, al pensar en ello, podría significar 2 dada la redacción de la pregunta.Usted podría incluir el resultado requerido mediante la alteración de su consulta:

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

Era una declaración de prueba, quería asegurarme de que mi código de Hibernate hacía su asignación correctamente y extraía los valores correctos de la base de datos. – Sergey

+0

Bueno, si este es un caso de prueba específico, ¿por qué no simplemente recorre los objetos recuperados y falla la prueba si no se encuentra la ID deseada? ¿Por qué tendrías todos los DTO's implementando la interfaz HasId solo para esto? –

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

es mejor romper el bucle 'para cada uno 'una vez que el valor del indicador es verdadero en lugar del bucle hasta el final –

0

Esto es lo que he usado en mi función DFS GetUnvisitedNeighbour.

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

Solía ​​trabajar en C#. Las expresiones Lambda en C# son mucho más fáciles de usar que en Java.

Puede usar la función filter para agregar una condición para la propiedad del elemento.

Luego use findFirst().get() o findAny.get() según su lógica.

Cuestiones relacionadas