Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将Java树映射代码迁移到Scala?_Java_Scala_Scala Collections_Treemap_Treeset - Fatal编程技术网

将Java树映射代码迁移到Scala?

将Java树映射代码迁移到Scala?,java,scala,scala-collections,treemap,treeset,Java,Scala,Scala Collections,Treemap,Treeset,我正在将我的Java代码库迁移到纯Scala,我被卡住了。我有一个IntervalMap的实现,也就是一个数据结构,它可以让你有效地将范围[从,到]映射到值,其中设置,删除和获取操作都是O(logn)(与IntervalTree或SegmentTree略有不同) 这段代码使用了Java的Java.util.TreeMaps,在迁移到Scala时,我遇到了两个大问题: Scala没有mutable.TreeMap-我决定使用mutable.TreeSet(奇怪的是Scala有mutable.Tre

我正在将我的Java代码库迁移到纯Scala,我被卡住了。我有一个IntervalMap的实现,也就是一个数据结构,它可以让你有效地将范围
[从,到]
映射到
,其中
设置
删除
获取
操作都是
O(logn)
(与IntervalTree或SegmentTree略有不同)

这段代码使用了Java的
Java.util.TreeMaps
,在迁移到Scala时,我遇到了两个大问题:

  • Scala没有
    mutable.TreeMap
    -我决定使用
    mutable.TreeSet
    (奇怪的是Scala有
    mutable.TreeSet
    ,但没有
    mutable.TreeMap
    )来存储键并将值存储在辅助
    mutable.Map
    。这是一个令人不快的黑客行为,但有没有更好的方法

  • 下一个问题是Scala的
    可变。TreeSet
    java.util.TreeSet
    ceilingKey
    FloorRentry
    pollFirst
    pollLast
    没有等价物,它们都是java中的
    O(logn)
    操作

  • 那么,如何最好地将代码迁移到Scala?在这些情况下,最佳做法是什么?我真的不想编写自己的树实现。有没有一种更惯用的Scala方式来编写我不知道的间隔图?还是有一些著名的图书馆?或者Scala只是简单地在这里吸吮它的gimpedtreeset和不存在的TreeMaps。当然,我可以在Scala中使用Java的
    TreeMap
    ,但这太难看了,我失去了所有优秀的Scala集合特性,我也可以使用Java


    下面是我当前的Java代码:

    不幸的是,答案是只使用Java
    TreeMap

    Scala并没有自己的所有副本,这是最显著的例外之一。它与Java兼容的原因之一是,您不必重新发明每个轮子

    您仍然希望使用Scala的原因是,并非您编写的每一段代码都与此树映射有关。您的
    IntervalMap
    可以是Scala
    IntervalMap
    ;您只需在内部使用Java
    TreeMap来实现它。或者您可以在Scala中使用不可变版本,它现在对于不可变版本的性能相当好


    也许在2.11或2.12中会有一个可变的
    树形图
    ;它需要有人编写、测试、优化等等,但我认为拥有它并没有哲学上的异议。

    您似乎想使用漂亮的Scala collections功能。我认为你不需要重新实施你的课程

    你看过scala.collection.JavaConversions吗

    您可以采用类似的方法使用包装器,然后相应地实现所需的方法。您可能需要在如何定义和使用地图特有的方法方面更具创造性,但这不应该是什么大问题

    我希望这能给你一个想法。如果您需要更多的指导,请告诉我,我可以帮您解决(看起来您已经有一段时间没有问了)。

    1)在内部使用不可变树映射有什么问题?它的效率和可变树映射差不多,一切都在O(logn)中完成

    2) 在Scala版本中,没有
    ceilingKey
    floorKey
    ,而是有
    from
    to
    的方法,这些方法基本相同,但返回的是整个子树而不是单个条目

    Java代码的完整1:1端口:

    import scala.collection._
    import scala.collection.immutable.TreeMap
    
    case class Segment[T](start: Int, end: Int, value: T) {
      def contains(x: Int) = (start <= x) && (x < end)
      override def toString = "[%d,%d:%s]".format(start, end, value)
    }
    
    class IntervalMap[T] {
      private var segments = new TreeMap[Int, Segment[T]]
      private def add(s: Segment[T]): Unit = segments += (s.start -> s)
      private def destroy(s: Segment[T]): Unit = segments -= s.start
      def ceiling(x: Int): Option[Segment[T]] = {
        val from = segments.from(x)
        if (from.isEmpty) None
        else Some(segments(from.firstKey))
      }
      def floor(x: Int): Option[Segment[T]] = {
        val to = segments.to(x)
        if (to.isEmpty) None
        else Some(segments(to.lastKey))
      }
      def find(x: Int): Option[Segment[T]] = {
        floor(x).filter(_ contains x).orElse(ceiling(x))
      }
    
      // This is replacement of `set`, used as myMap(s,e) = v
      def update(x: Int, y: Int, value: T): Unit = {
        require(x < y)
        find(x) match {
          case None => add(Segment[T](x, y, value))
          case Some(s) => {
            if (x < s.start) {
              if (y <= s.start) {
                add(Segment[T](x, y, value))
              } else if (y < s.end) {
                destroy(s)
                add(Segment[T](x, y, value))
                add(Segment[T](y, s.end, s.value))
              } else {
                destroy(s)
                add(Segment[T](x, s.end, value))
                this(s.end, y) = value
              }
            } else if (x < s.end) {
              destroy(s)
              add(Segment[T](s.start, x, s.value))
              if (y < s.end) {
                add(Segment[T](x, y, value))
                add(Segment[T](y, s.end, s.value))
              } else {
                add(Segment[T](x, s.end, value))
                this(s.end, y) = value
              }
            } else {
              throw new IllegalStateException
            }
          }
        }
      }
    
      def get(x: Int): Option[T] = {
        for (seg <- floor(x); if (seg contains x)) yield seg.value
      }
    
      def apply(x: Int) = get(x).getOrElse{
        throw new NoSuchElementException(
          "No value set at index " + x
        )
      }
    
      override def toString = segments.mkString("{", ",", "}")
    }
    
    // little demo
    val m = new IntervalMap[String]
    println(m)
    m(10, 20) = "FOOOOOOOOO"
    m(18, 30) = "_bar_bar_bar_"
    m(5, 12) = "bazzz"
    println(m)
    
    for (x <- 1 to 42) printf("%3d -> %s\n",x,m.get(x))
    

    Segment
    类应该设置为
    private[yourPackage]
    ,应该添加一些文档。

    Scala 2.12具有
    mutable.TreeMap
    最后:

    该链接并没有真正回答我关于如何实际迁移代码的问题。最佳实践/习惯用法等是什么?最后,我仍然没有一个与
    floorrentry
    等价的东西。在著名的Scala库中是否有
    mutable.TreeMap
    和/或
    IntervalMap
    本身的实现?对于TreeMap是
    from
    to
    ,O(logn)??如果不是,在代码中,操作不是对数的。。。顺便说一句,这是我在Scala中的实现(它是O(n)而不是O(logn),其中n是段数:我上面链接的Java是O(logn)。为什么不应该在O(logn)中呢?这与
    ceil
    floor
    的操作大致相同,但不是沿着树走到叶子节点,而是沿着树走,并将路径存储在大小为
    O(log n)的列表中
    ,最终修剪所访问节点的两个子节点中的一个子节点。如果需要,可以在此处查看底层RedBlackTree的实现:,尤其是
    doFrom
    方法,它似乎是实际
    from
    方法的“递归工作马”。
    {}
    {5 -> [5,12:bazzz],12 -> [12,18:FOOOOOOOOO],18 -> [18,20:_bar_bar_bar_],20 -> [20,30:_bar_bar_bar_]}
      1 -> None
      2 -> None
      3 -> None
      4 -> None
      5 -> Some(bazzz)
      6 -> Some(bazzz)
      7 -> Some(bazzz)
      8 -> Some(bazzz)
      9 -> Some(bazzz)
     10 -> Some(bazzz)
     11 -> Some(bazzz)
     12 -> Some(FOOOOOOOOO)
     13 -> Some(FOOOOOOOOO)
     14 -> Some(FOOOOOOOOO)
     15 -> Some(FOOOOOOOOO)
     16 -> Some(FOOOOOOOOO)
     17 -> Some(FOOOOOOOOO)
     18 -> Some(_bar_bar_bar_)
     19 -> Some(_bar_bar_bar_)
     20 -> Some(_bar_bar_bar_)
     21 -> Some(_bar_bar_bar_)
     22 -> Some(_bar_bar_bar_)
     23 -> Some(_bar_bar_bar_)
     24 -> Some(_bar_bar_bar_)
     25 -> Some(_bar_bar_bar_)
     26 -> Some(_bar_bar_bar_)
     27 -> Some(_bar_bar_bar_)
     28 -> Some(_bar_bar_bar_)
     29 -> Some(_bar_bar_bar_)
     30 -> None
     31 -> None
     32 -> None
     33 -> None
     34 -> None
     35 -> None