如何从scala中的文件中读取不可变数据结构

Fil*_*sso 5 scala mutable immutability data-structures

我有一个由Jobs组成的数据结构,每个都包含一组Tasks.作业和任务数据都在以下文件中定义:

jobs.txt:
JA
JB
JC

tasks.txt:
JB  T2
JA  T1
JC  T1
JA  T3
JA  T2
JB  T1 
Run Code Online (Sandbox Code Playgroud)

创建对象的过程如下:
- 读取每个作业,创建它并通过id存储它
- 读取任务,通过id检索作业,创建任务,在作业中存储任务

读取文件后,永远不会修改此数据结构.所以我希望作业中的任务存储在一个不可变的集合中.但我不知道如何以有效的方式做到这一点.(注意:存储作业的不可变映射可能不可变)

这是代码的简化版本:

class Task(val id: String) 

class Job(val id: String) {
    val tasks = collection.mutable.Set[Task]() // This sholud be immutable
}

val jobs = collection.mutable.Map[String, Job]() // This is ok to be mutable

// read jobs
for (line <- io.Source.fromFile("jobs.txt").getLines) { 
    val job = new Job(line.trim)
    jobs += (job.id -> job)
}

// read tasks
for (line <- io.Source.fromFile("tasks.txt").getLines) {
    val tokens = line.split("\t")
    val job = jobs(tokens(0).trim)
    val task = new Task(job.id + "." + tokens(1).trim)
    job.tasks += task
}
Run Code Online (Sandbox Code Playgroud)

提前感谢您的每一个建议!

Rex*_*err 4

最有效的方法是将所有内容读入可变结构,然后最后转换为不可变结构,但这可能需要对具有大量字段的类进行大量冗余编码。因此,请考虑使用与底层集合使用的相同模式:具有新任务的作业是一个新作业

这是一个甚至不需要阅读作业列表的示例 - 它从任务列表中推断出来。(这是在 2.7.x 下工作的示例;最新版本的 2.8 使用“Source.fromPath”而不是“Source.fromFile”。)

object Example {
  class Task(val id: String) {
    override def toString = id
  }

  class Job(val id: String, val tasks: Set[Task]) {
    def this(id0: String, old: Option[Job], taskID: String) = {
      this(id0 , old.getOrElse(EmptyJob).tasks + new Task(taskID))
    }
    override def toString = id+" does "+tasks.toString
  }
  object EmptyJob extends Job("",Set.empty[Task]) { }

  def read(fname: String):Map[String,Job] = {
    val map = new scala.collection.mutable.HashMap[String,Job]()
    scala.io.Source.fromFile(fname).getLines.foreach(line => {
      line.split("\t") match {
        case Array(j,t) => {
          val jobID = j.trim
          val taskID = t.trim
          map += (jobID -> new Job(jobID,map.get(jobID),taskID))
        }
        case _ => /* Handle error? */
      }
    })
    new scala.collection.immutable.HashMap() ++ map
  }
}

scala> Example.read("tasks.txt")
res0: Map[String,Example.Job] = Map(JA -> JA does Set(T1, T3, T2), JB -> JB does Set(T2, T1), JC -> JC does Set(T1))
Run Code Online (Sandbox Code Playgroud)

另一种方法是读取作业列表(将作业创建为 new Job(jobID,Set.empty[Task])),然后处理任务列表包含不在作业列表中的条目时的错误情况。(每次读入新任务时,您仍然需要更新作业列表映射。)