La ragione che particolare codice è lento è perché sta lavorando su primitive, ma sta usando operazioni generiche, per cui i primitivi devono essere inscatolato. (Questo potrebbe essere migliorato se List
e i suoi antenati fossero specializzati.) Questo probabilmente rallenterà le cose di un fattore 5 o giù di lì.
Inoltre, dal punto di vista algoritmico, tali operazioni sono alquanto costose, perché si crea un'intera lista e quindi si crea una lista completamente nuova che allontana alcuni componenti della lista intermedia. Se lo facessi in un colpo solo, staresti meglio. Si potrebbe fare qualcosa di simile:
list collect (case e if (e*2>10) => e*2)
ma cosa succede se il calcolo e*2
è molto costoso? Poi si potrebbe
(List[Int]() /: list)((ls,e) => { val x = e*2; if (x>10) x :: ls else ls }
solo che questa sembrerebbe all'indietro. (Si potrebbe invertire se necessario, ma ciò richiede la creazione di un nuovo elenco, che di nuovo non è l'algoritmo ideale.)
Naturalmente, si ha lo stesso tipo di problemi algoritmici in Java se si utilizza un singolo lista collegata - la tua nuova lista finirà all'indietro, oppure dovrai crearla due volte, prima in senso inverso e poi in avanti, oppure devi costruirla con ricorsione (non-coda) (che è facile in Scala, ma sconsigliabile per questo genere di cose in entrambe le lingue dato che esaurirai la pila), o devi creare una lista mutabile e poi fingere dopo che non è mutabile. (Che, per inciso, si può fare in Scala anche - vedi mutable.LinkedList
.)
fonte
2011-02-04 15:02:35
Questa risposta ha il problema, ma non offre una soluzione piacevole. – Raphael
@Raphael - Non ce n'è davvero uno dato lo stato attuale della libreria. 'view' /' force' non ti salverà quando lavori con i primitivi. –
Se 'e * 2' erano costosi, il costo di avere il passo intermedio diminuirebbe. Forse problemi di memoria, se gestisci grandi quantità di dati. – ziggystar