método Java: Encontrar objeto en lista de arreglo dado un valor de atributo conocido

StackOverflow https://stackoverflow.com/questions/739192

  •  09-09-2019
  •  | 
  •  

Pregunta

Tengo un par de preguntas realidad.

Tengo una clase perro con los siguientes campos de instancia:

private int id;
private int id_mother;
private int id_father;
private String name="";
private String owner="";
private String bDate="";

También tengo una clase Archivo que se puede crear una instancia de perro y poner Perro objetos en un ArrayList.

Estoy tratando de escribir un método en el Archivo que toma un entero como ID y mira a través del ArrayList, y devuelve el objeto que contiene dicho ID.

private Dog getDog(int id){
    Dog dog = new Dog();
    int length=getSize();
    int i=0;

    dog=al.get(i);
    i++;

    while(dog.getId()!=id && i<length)
        dog=al.get(i);
        i++;

    if(dog.getId()!=id)
        dog=null;
    return dog;
}//end getDog

Hay dos problemas con este método (los otros métodos que utilizan trabajo). En primer lugar no está funcionando, y no puedo ver por qué. Estoy mientras-bucle a través de (potencialmente) todos los objetos en el ArrayList, para a continuación, después de que se termina el ciclo, comprobando si el bucle terminó porque se quedó sin objetos para buscar a través de, o porque se encontró un objeto con el ID dado . En segundo lugar, que parece como un proceso que consume tiempo inmensamente. ¿Hay alguna manera de acelerar este proceso?

¿Fue útil?

Solución

A while se aplica a la expresión o bloque después de la while.

Usted no tiene un bloque, por lo que su tiempo termina con la expresión dog=al.get(i);

while(dog.getId()!=id && i<length)
                dog=al.get(i);

Todo después de que ocurre sólo una vez.

No hay razón para un nuevo perro, como nunca estás usando el perro que new'd arriba; se asigna inmediatamente un perro de la matriz para su referencia perro.

Y si usted necesita para obtener un valor para una clave, se debe utilizar un mapa, no un Array.

Editar: esta fue la razón por donwmodded ??

Comentario de OP:

  

Una cuestión adicional con respecto a no tener que hacer una nueva instancia de un perro. Si sólo estoy sacando copias de los objetos de la lista de arreglo, ¿cómo puedo luego se lo quita de la lista de arreglo sin tener un objeto en el que he puesto? Me acabo de dar cuenta, así que no agrupen el bucle while.

Una referencia Java y el objeto se refiere a diferentes cosas. Son muy parecido a un C ++ de referencia y objeto, aunque una referencia de Java puede ser re-señaló como un puntero ++ C.

El resultado es que Dog dog; o Dog dog = null le da una referencia que apunta a ningún objeto. new Dog() crea un objeto que puede ser señaló.

Después de que con un dog = al.get(i) significa que la referencia apunta ahora a la referencia perro devuelto por al.get(i). Entienden, en Java, los objetos no se devuelven, sólo referencias a objetos (que son las direcciones del objeto en la memoria).

El puntero / referencia / dirección del perro que newed hasta ahora se pierde, ya que ningún código se refiere a ella, como el referente fue reemplazado con el referente que obtuvo de al.get(). Eventualmente, el recolector de basura de Java va a destruir ese objeto; en C ++ que le ha "filtrado" por la memoria.

El resultado es que usted necesita para crear una variable que puede referirse a un perro; no es necesario para crear un perro con los new.

(En verdad, no es necesario crear una referencia, ya que lo que realmente debería estar haciendo es regresar lo vuelve un mapa de su get () Función Si el mapa no es parametrizada en el perro, como este.: Map<Dog>, entonces usted tendrá que emitir el regreso de conseguir, pero que no se necesita una referencia: return (Dog) map.get(id); o si el mapa está parametrizado, return map.get(id) y eso es una línea entera de su función, y va a ser más rápido que la iteración. una matriz para la mayoría de los casos.)

Otros consejos

Si se asume que usted ha escrito un método para el perro es igual que compara correctamente basado en el id del perro de la manera más fácil y sencilla para devolver un elemento de la lista es la siguiente.

if (dogList.contains(dog)) {
   return dogList.get(dogList.indexOf(dog));
}

Eso es menos intensivo que el rendimiento de otros enfoques aquí. No es necesario un bucle en absoluto en este caso. Espero que esto ayude.

P.S Puede utilizar Apache Commons Lang escribir un simple método equals para el perro de la siguiente manera:

@Override
public boolean equals(Object obj) {     
   EqualsBuilder builder = new EqualsBuilder().append(this.getId(), obj.getId());               
   return builder.isEquals();
}

Para mejorar el rendimiento de la operación, si siempre va a querer para buscar objetos por algún identificador único, entonces es posible considerar el uso de un Map<Integer,Dog> . Esto proporcionará a las operaciones de búsqueda en tiempo constante por parte de la clave. Todavía se puede iterar sobre los propios objetos usando el mapa values().

Un fragmento de código rápido para empezar:

// Populate the map
Map<Integer,Dog> dogs = new HashMap<Integer,Dog>();
for( Dog dog : /* dog source */ ) {
    dogs.put( dog.getId(), dog );
}

// Perform a lookup
Dog dog = dogs.get( id );

Esto ayudará a acelerar las cosas un poco si usted está realizando múltiples operaciones de búsqueda de la misma naturaleza en la lista. Si acaba de hacer la única de búsqueda, entonces usted va a incurrir en el mismo circuito de sobrecarga independientemente.

Usted tiene que recorrer toda la matriz, no hay que cambiar. Sin embargo, puede hacerlo un poco más fácil

for (Dog dog : list) {
  if (dog.getId() == id) {
    return dog; //gotcha!
  }
}
return null; // dog not found.

o sin el nuevo bucle for

for (int i = 0; i < list.size(); i++) {
  if (list.get(i).getId() == id) {
    return list.get(i);
  }
}

Yo estaba interesado en ver que el cartel original utilizaba un estilo que evita la salida temprana. Sola entrada; Salir sola (SESE) es un estilo interesante que no he explorado realmente. Es tarde y tengo una botella de sidra, por lo que he escrito una solución (no probado) y sin una salida temprana.

Debería haber usado un iterador. Desafortunadamente java.util.Iterator tiene un efecto secundario en el método get. (No me gusta el diseño Iterator debido a sus ramificaciones de excepción.)

private Dog findDog(int id) {
    int i = 0;
    for (; i!=dogs.length() && dogs.get(i).getID()!=id; ++i) {
        ;
    }

    return i!=dogs.length() ? dogs.get(i) : null;
}

Tenga en cuenta la duplicación de la expresión i!=dogs.length() (dogs.get(i).getID()!=id podría haber elegido).

Si usted tiene que conseguir un atributo que no es el ID. Me gustaría utilizar CollectionUtils .

Dog someDog = new Dog();
Dog dog = CollectionUtils(dogList, new Predicate() {

@Override
public boolean evaluate(Object o)
{
    Dog d = (Dog)o;
    return someDog.getName().equals(d.getName());
}
});

I resuelto este usando java 8 lambdas

int dogId = 2;

return dogList.stream().filter(dog-> dogId == dog.getId()).collect(Collectors.toList()).get(0);
List<YourClass> list = ArrayList<YourClass>();


List<String> userNames = list.stream().map(m -> m.getUserName()).collect(Collectors.toList());

salida: [ "John", "Alex"]

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top