Scala replacement for Arrays.binarySearch?

前端 未结 6 1697
故里飘歌
故里飘歌 2020-12-29 03:18

Is there a replacement in Scala for Java\'s int Arrays.binarySearch(Object[] array, object)?

The problem is that Scala\'s Arrays are not covariant, so I

6条回答
  •  小蘑菇
    小蘑菇 (楼主)
    2020-12-29 04:05

    Been some years since this question was raised, thought to make some comparison test, hopefully it can help some to decide:

    import scala.collection.Searching._
    import _root_.scala.collection.JavaConversions._
    import java.util.{Collections, List => JList}
    import scala.reflect.ClassTag
    
    class ObjectArrayTools[T <: Int](a: Array[T]) {
       def binarySearch(key: T) = {
         java.util.Arrays.binarySearch(a.asInstanceOf[Array[Int]],key)
       }
    }
    
    class SearchableSeq[T](a: Seq[T])(implicit ordering: Ordering[T]) {
        val list: JList[T] = a.toList
        def binarySearch2(key: T): Int = Collections.binarySearch(list, key, ordering)
    }
    
    object BinarySearch {
      implicit def anyrefarray_tools[T <: Int](a: Array[T]) = new ObjectArrayTools(a)
      implicit def seqToSearchable[T](a: Seq[T])(implicit ordering: Ordering[T]) =
              new SearchableSeq(a)(ordering)
    
      def main(args:Array[String]) {
        val informationArray = Array(1,2,3,4,5,6,7,8,9,10,11,12,14,15,18,20,22,23,25,26)
        val informationList = List(1,2,3,4,5,6,7,8,9,10,11,12,14,15,18,20,22,23,25,26)
        //val sortedArray = sortList(informationArray)
        val sortedArray = informationArray
        val sortedList = informationList
    
        for(x <- 0 to 2) {
          val startTime = System.nanoTime
          val result = binarySearch(sortedArray, 5)
          val result2 = binarySearch(sortedArray, 19)
          println(s"Custom search time elapsed: ${(System.nanoTime - startTime)}")
    
          val startTime2 = System.nanoTime
          val result3 = sortedArray.search(5)
          val result4 = sortedArray.search(19)
          println(s"Scala search time elapsed: ${(System.nanoTime - startTime2)}")
    
          val startTime3 = System.nanoTime
          val result5 = sortedArray.binarySearch(5)
          val result6 = sortedArray.binarySearch(19)
          println(s"Java search casting time elapsed: ${(System.nanoTime - startTime3)}")
    
          val startTime4 = System.nanoTime
          val result7 = sortedList.binarySearch2(5)
          val result8 = sortedList.binarySearch2(19)
          println(s"Java search as list time elapsed: ${(System.nanoTime - startTime4)}")
    
    
          val startTime9 = System.nanoTime
          val result10 = binarySearchWithImplicitConversion(sortedArray, 5)
          val result11 = binarySearchWithImplicitConversion(sortedArray, 19)
          println(s"Custom generic time elapsed: ${(System.nanoTime - startTime9)}")
    
          println("---")
        }
      }
    
      /*def sortList(list:Array[Int]):Array[Int] = {
        import com.walcron.etc.Quicksort._
        quickSort(list)
      }*/
    
      //def binarySearch[T <% Ordered[T]](list:Array[T], valueToBeSearch:T)(implicit t:ClassTag[T]):Int =  {
      def binarySearch(list:Array[Int], valueToBeSearch:Int):Int =  {
        def search(start:Int, end:Int):Int = {
          val pos = ((end - start) / 2) + start
          val curr = list(pos)
    
          if(curr == valueToBeSearch) {
            pos
          }
          else if((end - start) <= 1) {
            -1 * (pos + 1) // Indicates the value should be inserted
          }
          else if(valueToBeSearch > curr) {
            search(pos, end)
          }
          else {
            search(start, pos)
          }
        }
    
        search(0, list.length)
      }
    
      def binarySearchWithImplicitConversion[T <% Ordered[T]](list:Array[T], valueToBeSearch:T)(implicit t:ClassTag[T]):Int =  {
        def search(start:Int, end:Int):Int = {
          val pos = ((end - start) / 2) + start
          val curr = list(pos)
    
          if(curr == valueToBeSearch) {
            pos
          }
          else if((end - start) <= 1) {
            -1 * (pos + 1) // Indicates the value should be inserted
          }
          else if(valueToBeSearch > curr) {
            search(pos, end)
          }
          else {
            search(start, pos)
          }
        }
    
        search(0, list.length)
      }
    }
    

    The returned result after 3 runs (as Scala compiler really do need some boost)

    Custom search time elapsed: 873373
    Scala search time elapsed: 9322723
    Java search casting time elapsed: 126380
    Java search as list time elapsed: 7375826
    Custom generic time elapsed: 4421972
    ---
    Custom search time elapsed: 10372
    Scala search time elapsed: 34885
    Java search casting time elapsed: 10861
    Java search as list time elapsed: 104596
    Custom generic time elapsed: 57964
    ---
    Custom search time elapsed: 9121
    Scala search time elapsed: 31667
    Java search casting time elapsed: 11815
    Java search as list time elapsed: 53387
    Custom generic time elapsed: 60773
    

    In general, java binary search performed way better; while scala's search did pretty bad. There was also another noticeable performance, it seems that generic typing implicitly drags the performance here badly(so maybe someone can help fix the generic type)...but indirectly it shows a big performance impact.

提交回复
热议问题