2013-04-17 2 views
1

정의 된 크기의 따옴표 목록 이동 평균을 계산하는 간단한 스칼라 프로그램을 작성했습니다. 초당 약 5-6 인용의 속도로 시세가 올 것입니다.스칼라 - 선택할 수있는 변경 가능 ListBuffer 또는 변경 불가능 목록?

1) 불변의 스칼라 목록에 따옴표를 넣어두면 좋을까요? 견적이 올 때마다 새로운 목록이 만들어 질 것입니다. 너무 많은 불필요한 기억을 차지할 것인가?

또는

2)이 좋은 내가 가장 오래된 견적을 제거하고 새로운 따옴표에게 견적이 올 때마다 밀어 것이다 것을 특징으로 ListBuffer 같은 변경 가능한 목록에서 따옴표를 유지하는 것입니다.

현재 코드

package com.example.csv 

import scala.io.Source 
import scala.collection.mutable.ListBuffer 

object CsvFileParser { 
    val WINDOW_SIZE = 25; 
    var quotes = ListBuffer(0.0); 
    def main(args: Array[String]) = { 
    val src = Source.fromFile("GBP_USD_Week1.csv"); 
    //drop header and split the comma separated tokens 
    val iter = src.getLines().drop(1).map(_.split(",")); 
    // Sliding window reads ahead // remove it 
    val index = 0; 

    while(iter.hasNext) { 
    processRecord(iter.next) 
    } 
    src.close() 
    } 

    def processRecord(record: Array[String]) = { 
    if(quotes.length < WINDOW_SIZE){ 
     quotes += record(4).toDouble; 
    }else { 
     val movingAverage = quotes.sum/quotes.length 
     quotes.map(_ + " ").foreach(print) 
     println("\nMoving Average " + movingAverage) 
     quotes = quotes.tail; 
     quotes += record(4).toDouble; 

    } 
    } 

    /*def simpleMovingAverage(values: ListBuffer[Double], period: Int): ListBuffer[Double] = { 
     ListBuffer.fill(period - 1)(0.0) ++ (values.sliding(period).map(_.sum).map(_/period)) 
    }*/ 

} 
+2

이것은 불변 가변 컬렉션의 각종 동작에 대한 좋은 참고이다 http://www.scala-lang.org/docu/files/collections-api/collections_40.html. 최상의 성능 특성을 가진 작업을 사용하십시오. – Brian

답변

4

이 당신이 역순 여부 항목을 유지 여부에 따라 달라집니다. List은 처음에 일정한 시간에 요소를 추가합니다 (:: 이 아님). ListBuffer#+=은 목록 끝에 추가 할 노드를 만듭니다.

내부적으로는 동일한 데이터 구조 인 ListListBuffer 사이에 성능 차이가 거의 없거나 메모리 풋 프린트의 차이가 없어야합니다. 유일한 질문은 reverse 끝까지해야 할 것입니다 - 원한다면 두 번째 목록을 만들어야하므로 속도가 느려질 수 있습니다.

목록 버퍼를 사용하기로 결정한 것이 맞습니다. 첫 번째 요소를 제거하고 컬렉션의 다른쪽에 추가해야합니다. 이는 일반 기능 목록에서 효율적으로 수행 할 수없는 항목입니다.

그러나 코드에서 ListBuffertail을 호출합니다. 이것은 실제로 당신에게 값싼 꼬리 (O(WINDOW_SIZE) 연산)를주기보다는 목록 버퍼의 내용을 복사합니다. 첫 번째 항목을 제거하려면 quotes.remove(0, 1)으로 전화해야합니다. 이것은 현재 버퍼 O(1) 작업을 변경합니다.

매우 빠른 견적을 받으려면 사용자 지정 데이터 구조를 사용하는 것이 좋습니다. 목록 버퍼에는 복싱 비용을 지불해야합니다. 그러나 초당 5-6 따옴표가 있고 WINDOW_SIZE이 약 100 인 경우 목록 버퍼의 tail을 호출해도 수용 할 수있는 수준 이상이어야합니다. 걱정할 필요가 없습니다.

0

스칼라의 변경 가능 구조는 구조 공유이라는 기술을 사용합니다. 는 목록을 위해 그것은 또한 Scaladocs에서 언급 한 것 :

기능적 목록 따라서 일부 시나리오에서 상당한 성능과 공간 소비 혜택을 제공하고, 지속성 및 구조 공유를 특징으로한다.

그래서 :

  • 불변 목록은 더 많은 공간을 차지합니다,하지만 훨씬 더 다른 SCLA를 구축 더 잘 조화됩니다
  • 변경할 수 버전 동시성하는 경향이있다 문제는 조금 더 빨라지고 litte bit less space를 사용합니다.

    • 당신이 변경 가능한 구조를 사용하는 경우, var에 제거 할 수는 불변 한
    • 그것은 간주됩니다 좋은 스타일을 덮어 쓰려면 보관 : 코드에 관해서는

    변경 가능한 구조체를 조작하거나 전역 변수가있는 대신 List를 반환하는 메서드가 있습니다

  • 아래 코드 조각 에서처럼 파일을 처리하면 파일을 닫을 필요가 없으며 파일도 동시에 처리됩니다

    데프 processLines (경로 : 문자열) : 단위 = 대한 { 라인 < - Source.fromFile ("GBP_USD_Week1.csv") getLines.tail.par 기록 < - line.split (",") .} processRecord (기록)

관련 문제