Optimización: Reemplace para el bucle con LESTITERATOR -- java campo con optimization campo con for-loop campo con while-loop campo con listiterator camp Relacionados El problema

Optimization: replace for loop with ListIterator


0
vote

problema

Español

Es mi primer trabajo en un proyecto bastante grande, y me han pedido que obtenga las mejores actuaciones.

Así que he hecho que reemplace mis bucles con un ListIterator , porque tengo alrededor de 180 bucles que llaman list.get(i) en listas con aproximadamente 5000 elementos. < / p>

Así que tengo dos preguntas.

1) ¿Son esos 2 fragmentos iguales? Quiero decir, ¿los producen la misma salida? Si no, ¿cómo puedo corregir el ListIterator ?

  ListIterator<Corsa> ridesIterator = rides.listIterator();     while (ridesIterator.hasNext()) {         ridesIterator.next();         Corsa previous = ridesIterator.previous(); //rides.get(i-1)         Corsa current = ridesIterator.next(); //rides.get(i)         if (current.getOP() < d.getFFP() && previous.getOA() > d.getIP() && current.wait(previous) > DP) {             doSomething();             break;         }     }  

__

  for (int i = 1; i < rides.size(); i++) {     if (rides.get(i).getOP() < d.getFP() && rides.get(i - 1).getOA() > d.getIP() && rides.get(i).getOP() - rides.get(i - 1).getOA() > DP) {         doSomething();             break;         }     }   

2) ¿Cómo será el primer fragmento si tengo algo como esto? (Cambiado I y su condición de salida)

  for (int i = 0; i < rides.size() - 1; i++) {     if (rides.get(i).getOP() < d.getFP() && rides.get(i + 1).getOA() > d.getIP() && rides.get(i).getOP() - rides.get(i + 1).getOA() > DP) {         doSomething();             break;         }     }   

Estoy preguntando porque es la primera vez que estoy usando un ListIterator6 y no puedo intentarlo ahora!

Editar: No estoy usando un Lista de Array, es una lista personalizada basada en una lista de enlaces

Editar 2: Estoy agregando algunas infos más. No puedo usar un sistema de almacenamiento en caché porque mis datos están cambiando en la iteración de Evry y administrar el caché sería difícil, ya que tendría que lidiar con datos inconsistentes. Ni siquiera puedo fusionar algunos de estos bucles en un bucle grande, ya que los tengo en diferentes métodos porque necesitan hacer muchas cosas diferentes.

Entonces, pegando este caso en particular, ¿cuál crees que es la mejor prattice? ¿Es Listerator la mejor manera de lidiar con mi caso? ¿Y cómo puedo usar elumiterator si mi bucle funciona entre 0 y tamaño-1?

Original en ingles

It's my first working on a quite big project, and I've been asked to obtain the best performances.

So I've thouhgt to replace my for loops with a ListIterator, because I've got around 180 loops which call list.get(i) on lists with about 5000 elements.

So I've got two questions.

1) Are those 2 snippets equal? I mean, do them produce the same output? If no, how can I correct the ListIterator thing?

ListIterator<Corsa> ridesIterator = rides.listIterator();     while (ridesIterator.hasNext()) {         ridesIterator.next();         Corsa previous = ridesIterator.previous(); //rides.get(i-1)         Corsa current = ridesIterator.next(); //rides.get(i)         if (current.getOP() < d.getFFP() && previous.getOA() > d.getIP() && current.wait(previous) > DP) {             doSomething();             break;         }     } 

__

for (int i = 1; i < rides.size(); i++) {     if (rides.get(i).getOP() < d.getFP() && rides.get(i - 1).getOA() > d.getIP() && rides.get(i).getOP() - rides.get(i - 1).getOA() > DP) {         doSomething();             break;         }     } 

2) How will it be the first snippet if I've got something like this? (changed i and its exit condition)

for (int i = 0; i < rides.size() - 1; i++) {     if (rides.get(i).getOP() < d.getFP() && rides.get(i + 1).getOA() > d.getIP() && rides.get(i).getOP() - rides.get(i + 1).getOA() > DP) {         doSomething();             break;         }     } 

I'm asking because it's the first time that I'm using a ListIterator and I can't try it now!

EDIT: I'm not using an ArrayList, it's a custom List based on a LinkedList

EDIT 2 : I'm adding some more infos. I can't use a caching system because my data is changing on evry iteration and managing the cache would be hard as I'd have to deal with inconsistent data. I can't even merge some of this loops into one big loop, as I've got them on different methods because they need to do a lot of different things.

So, sticking on this particular case, what do you think is the best pratice? Is ListIterator the best way to deal with my case? And how can I use the ListIterator if my for loop works between 0 and size-1 ?

              
       
       

Lista de respuestas

1
 
vote

Si conoce el tamaño máximo, obtendrá el mejor rendimiento si renunció a las colecciones, como ArrayList reemplazándolos con arreglos simples.

Por lo tanto, creando ArrayList<Corsa> con 5000 elementos, haz Corsa[] rides = new Corsa[5000] . En lugar de codificar de manera dura 5000 Úselo como final static int MAX_RIDES = 5000 por ejemplo, para evitar número mágico en el código. Luego itera con normal, refiriéndose a rides[i] .

En general, si busca un rendimiento, debe codificar en Java, como si fuera C / C ++ (por supuesto, donde pueda). El código no es tan orientado a objetos y hermoso, pero es rápido. Recuerde hacer la optimización siempre al final, cuando esté seguro, ha encontrado un cuello de botella. De lo contrario, sus esfuerzos son inútiles, solo hace que el código sea menos legible y se puede mantener. También use una Profiler , para asegurarse de que sus cambios son de hecho las actualizaciones, no bajadas.

Otro inconveniente de usar initialize0 es que asigna internamente la memoria. Así que GC (recolector de basura) se despertará más a menudo, lo que también puede tener impacto en el rendimiento general.

 

If you know the maximum size, you will get the best performance if you resign from collections such as ArrayList replacing them with simple arrays.

So instead creating ArrayList<Corsa> with 5000 elements, do Corsa[] rides = new Corsa[5000]. Instead of hard-coding 5000 use it as final static int MAX_RIDES = 5000 for example, to avoid magic number in the code. Then iterate with normal for, referring to rides[i].

Generally if you look for performance, you should code in Java, as if it was C/C++ (of course where you can). The code is not so object-oriented and beautiful, but it's fast. Remember to do optimization always in the end, when you are sure, you have found a bottleneck. Otherwise, your efforts are futile, only making the code less readable and maintainable. Also use a profiler, to make sure your changes are in fact upgrades, not downgrades.

Another downside of using ListIterator is that it internally allocates memory. So GC (Garbage Collector) will awake more often, which also can have impact on the overall performance.

 
 
     
     
1
 
vote
  1. No, no hacen lo mismo.

      initialize111  

    Las variables anteriores y actual contendrían el mismo valor "corsa", consulte el DOCUMENTACIÓN DE LISTERATOR Para más detalles (los iteradores están entre las posiciones "entre").

    El código correcto se vería de la siguiente manera:

      initialize2  
  2. El código en realidad se vería exactamente igual, solo la interpretación (como se muestra en los comentarios) sería diferente:

      initialize3  

de un punto de vista de optimización (prematuro?) La implementación de ListerTeterator es mejor.

  • Linkedlist es una lista de vínculos doblemente vinculados, lo que significa que cada elemento enlaza tanto a su predecesor (anterior), así como su sucesor (siguiente). Así que hace 3 referencias por bucle. = & gt; 3 * n
  • Cada vez que se obtiene (i) necesidades todos los elementos anteriores para llegar a la posición I Índice. Así que en promedio N / 4 referencias por bucle. (PERIFICARÁN N / 2, pero Linkedlist comienza desde el principio o el final de la lista). = & Gt; 2 * N * N / 4 == N ^ 2/2
 
  1. No they do not do the same.

    while (ridesIterator.hasNext()) {   ridesIterator.next();   Corsa previous = ridesIterator.previous(); //rides.get(i-1)   Corsa current = ridesIterator.next(); //rides.get(i) 

    The variables previous and current would contain the same "Corsa" value, see the ListIterator documentation for details (iterators are "in between" positions).

    The correct code would look as follows:

    while (ridesIterator.hasNext()) {   Corsa previous = ridesIterator.next(); //rides.get(i-1)   if(!ridesIterator.hasNext())     break; // We are already at the last element   Corsa current = ridesIterator.next(); //rides.get(i)   ridesIterator.previous(); // going back 1, to start correctly next time 
  2. The code would actually look exactly the same, only the interpretation (as shown in the comments) would be different:

    while (ridesIterator.hasNext()) {   Corsa previous = ridesIterator.next(); //rides.get(i)   if(!ridesIterator.hasNext())     break; // We are already at the last element   Corsa current = ridesIterator.next(); //rides.get(i+1)   ridesIterator.previous(); // going back 1, to start correctly next time 

From a (premature?) optimization viewpoint the ListIterator implementation is better.

  • LinkedList is a doubly-linked list which means that each element links to both its predecessor (previous) as well as its successor (next). So it does 3 referals per loop. => 3*N
  • Each get(i) needs to go through all previous elements to get to the i index position. So on average N/4 referals per loop. (You'd think N/2, but LinkedList starts from the beginning or the end of the list.) => 2 * N * N/4 == N^2 /2
 
 
0
 
vote

Aquí hay algunas sugerencias, con suerte, uno o dos serán aplicables a su situación.

  1. intente hacer solo un rides.get (x) por bucle.
  2. El método de caché resulta en variables locales según corresponda para su código.

En algunos casos, el compilador puede optimizar varias llamadas a la misma cosa que lo hace solo una vez, pero no siempre por muchos motivos sutiles. Como programador, si sabe por un hecho de que estos deben entregar los mismos valores, luego los almacenan en caché en las variables locales.

por ejemplo,

  int sz = rides.size (); float dFP = d.getFP ();  // wasn't sure of the type, so just called if float.. float dIP = d.getIP (); Corsa lastRide = rides.get ( 0 ); for ( int i = 1; i < sz; i++ ) {     Corsa = rides.get ( i );     float rOP = r.getOP ();     if ( rOP < dFP ) {         float lastRideOA = lastRide.getOA (); // only get OA if rOP < dFP         if ( lastRideOA > dIP && rOP - lastRideOA > DP ) {             doSomething ();             // maybe break;         }     }     lastRide = r; }   

Estas son optimizaciones que pueden no funcionar en todos los casos. Por ejemplo, si su doSomething expande la lista, entonces necesita recomputar SZ, o tal vez volver a hacer paseos. Sitio () cada iteración. Estas optimizaciones también asumen que la lista es estable en que los elementos no cambian durante el get..() . Si doSomething realiza cambios en la lista, entonces tendría que caché menos. Con suerte se entiende la idea. También puede aplicar algunas de estas técnicas a la forma del iterador del bucle también.

 

Here are some suggestions, hopefully one or two will be applicable to your situation.

  1. Try to do only one rides.get(x) per loop.
  2. Cache method results in local variables as appropriate for your code.

In some cases the compiler can optimize multiple calls to the same thing doing it just once instead, but not always for many subtle reasons. As a programmer, if you know for a fact that these should deliver the same values, then cache them in local variables.

For example,

int sz = rides.size (); float dFP = d.getFP ();  // wasn't sure of the type, so just called if float.. float dIP = d.getIP (); Corsa lastRide = rides.get ( 0 ); for ( int i = 1; i < sz; i++ ) {     Corsa = rides.get ( i );     float rOP = r.getOP ();     if ( rOP < dFP ) {         float lastRideOA = lastRide.getOA (); // only get OA if rOP < dFP         if ( lastRideOA > dIP && rOP - lastRideOA > DP ) {             doSomething ();             // maybe break;         }     }     lastRide = r; } 

These are optimizations that may not work in all cases. For example, if your doSomething expands the list, then you need to recompute sz, or maybe go back to doing rides.size() each iteration. These optimizations also assumes that the list is stable in that the elements don't change during the get..()'s. If doSomething makes changes to the list, then you'd need to cache less. Hopefully you get the idea. You can apply some of these techniques to the iterator form of the loop as well.

 
 
 
 

Relacionados problema

0  ¿Cómo obtener la combinación requerida de dos números de un arraylist?  ( How to get the required combination of two numbers from an arraylist ) 
Tengo una lista de array de algunos elementos path = [1, 2, 5, 7] . Ahora quiero obtener valores de estos elementos como: 1,2 2,5 5,7 Utilicé el ite...

1  Método eliminar () del iterador en Linkedlist  ( Method remove of iterator in linkedlist ) 
Podría alguien explicarme cómo funciona este método, a través de. Este lugar if (next == lastReturned) . No entiendo en qué caso next puede ser igual last...

3  Excepción de modificación concurrente en Java [duplicado]  ( Concurrent modification exception in java ) 
Esta pregunta ya tiene respuestas aquí : iterando a través de una colección, evitando concurrentmodi...

0  Implementando iteradores y Const_iterators  ( Implementing iterators and const iterators ) 
Estoy teniendo un problema con la compilación con respecto a una clase de lista doblemente vinculada con el iterador anidado y las clases de Const_iterator en...

1  Java: Evite la excepción de modificación concurrente con Listerator mientras modifica una lista en un bucle  ( Java avoid concurrent modification exception with listiterator while modifying ) 
Uso de Java, tengo una lista para verificar y, en caso de que uno de los sublistas recuperados a través de un bucle se encuentra con alguna condición, debe re...

1  ITERADOR C ++ al último elemento de una lista vinculada?  ( C iterator to last element of a linked list ) 
Me gustaría obtener el ::iterator en el último elemento del list6 . Mi comprensión es que puede obtener el iterador en el .front() de la lista con .be...

1  Usando unisteriterator  ( Using a listiterator ) 
Tengo una tarea que estoy teniendo dificultades para completar. Es un laboratorio de dos partes que demuestra las clases de LinkedList y colas. Tengo que usar...

7  Índice del elemento mínimo en un STD :: LISTA  ( Index of minimum element in a stdlist ) 
Si tengo un std::vector<int> , puedo obtener el índice del elemento mínimo al restar dos iteradores: int min_index = std::min_element(vec.begin(), vec.end...

3  ¿Cómo eliminar condicionalmente un elemento de una lista con un iterador?  ( How to conditionally remove an element from a list using an iterator ) 
problema: Estoy escribiendo una aplicación de administrador de archivos simple. En este programa tengo una clase de "directorio": class Directory { pub...

-1  ¿Cómo sabe un iterador en Java cuándo arrojar una excepción de modificación de concurrentes?  ( How does an iterator in java know when to throw concurrentmodification exception ) 
Tengo el siguiente código que lanza concurrentmodificationException porque estoy usando dos iteradores diferentes en la misma lista y uno de ellos está modifi...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos