Scala Array和List的区别
Difference between Array and List in scala
Q:什么时候用Array(Buffer)和List(Buffer)?
A:Scala中的List是不可变的递归数据(immutable recursive data),是Scala中的一种基础结构,你应该多用List而不是Array(Array实际上是mutable,不可变(immutable)的Array是IndexedSeq)
Mutable Structures
ListBuffer提供一个常数时间的转换到List。
一个Scala的Array应该是由Java array生成的,因此一个Array[Int]也许比List[Int]更有效率。
但是,我认为Scala中数组尽量少用,因为它感觉是你真的需要知道底层发生了什么,来决定是否Array将所需的基本数据类型进行备份,或者可能boxed as a wrapper type.
Performance differences | Array | List |
---|---|---|
Access the ith element | O(1) | O(i) |
Discard the ith element | O(n) | O(i) |
Insert an element at i | O(n) | O(i) |
Reverse | O(n) | O(n) |
Concatenate (length m,n) | O(n+m) | O(n) |
Calculate the length | O(1) | O(n) |
memory differences | Array | List |
---|---|---|
Get the first i elements | O(i) | O(i) |
Drop the first i elements | O(n-i) | O(1) |
Insert an element at i | O(n) | O(i) |
Reverse | O(n) | O(n) |
Concatenate (length m,n) | O(n+m) | O(n) |
所以,除非你需要快速随机访问或需要count batches of elements,否则,列表比数组更好。
Scala快排List和Array数组效率实测
代码
package com.tingfeng.scala.test
import scala.annotation.tailrec
import scala.util.{Random, Sorting}
object SortTest {
def initRandomList(size :Int):List[Int]={
val random = new Random()
def initList(size :Int,random: Random):List[Int] = size match {
case 0 => Nil
case 1 => List(random.nextInt())
case s:Int =>
val value = s / 2
if( s % 2 == 0) {
initList(value,random) ++ initList(value,random)
}else{
initList(value,random) ++ initList(value + 1,random)
}
}
initList(size,random)
}
def printTime(call : => Unit,tag: String = ""){
val startTime = System.currentTimeMillis()
println(tag)
call
println
println(s"use time : ${System.currentTimeMillis() - startTime}\n")
}
def swap(array: Array[Int],x:Int,y:Int):Unit ={
val t = array(x) ^ array(y)
array(x) = t ^ array(x)
array(y) = t ^ array(y)
}
def doThing[A<:Any](any: A,call: A => Unit):A = {
call(any)
any
}
def printList[A<%Seq[Any]](seq:A,size :Int = 10):Unit={
seq.splitAt(size)._1.foreach(it => print(s"$it,"))
}
def shuffleIntSeq(seq: Array[Int],size: Int):Unit={
val random = new Random()
val maxSize = size/2
for(i <- 0 to maxSize){
swap(seq,i,maxSize + random.nextInt(maxSize))
}
}
def main(args: Array[String]): Unit = {
val size = 5000000
val printSize = 10
val list = initRandomList(size)
//打印出钱100个,和List快速排序的时间花费
printTime(printList[List[Int]](qSortList(list),Math.min(10,size)),"qSortList")
val array = list.toArray
printTime(printList[Array[Int]](doThing[Array[Int]](array,Sorting.quickSort),Math.min(printSize,size)),"Sorting.quickSort")
shuffleIntSeq(array,size)
printTime(printList[Array[Int]](doThing[Array[Int]](array,qSortArray1),Math.min(printSize,size)),"qSortArray1")
shuffleIntSeq(array,size)
printTime(printList[Array[Int]](doThing[Array[Int]](array,qSortArray2),Math.min(printSize,size)),"qSortArray2")
shuffleIntSeq(array,size)
printTime(printList[Array[Int]](doThing[Array[Int]](array,qSortArray3),Math.min(printSize,size)),"qSortArray3")
shuffleIntSeq(array,size)
printTime(printList[Array[Int]](doThing[Array[Int]](array,qSortArray4),Math.min(printSize,size)),"qSortArray4")
}
def qSortList(list: List[Int]):List[Int] = list match {
case Nil => Nil
case head :: other =>
val (left, right) = other.partition(_ < head)
(qSortList(left) :+ head) ++ qSortList(right)
}
def qSortArray1(array: Array[Int]):Unit = {
def sort(ay : Array[Int],start: Int,end: Int):Unit={
if(start >= end) {
return
}
val head = ay(start)
var spliteIndex = start
for (i <- start + 1 to end){
if(ay(i) < head){
swap(array,spliteIndex,i)
spliteIndex += 1
}
}
if(start != spliteIndex){
sort(ay, start, spliteIndex)
}
if(start == spliteIndex){
spliteIndex += 1
}
if(spliteIndex != end){
sort(ay, spliteIndex, end)
}
}
sort(array,0,array.size - 1)
}
def qSortArray2(array: Array[Int]) {
def sort(l: Int, r: Int) {
val pivot = array((l + r) / 2)
var lv = l; var rv = r
while (lv <= rv) {
while (array(lv) < pivot) lv += 1
while (array(rv) > pivot) rv -= 1
if (lv <= rv) {
swap(array,lv, rv)
lv += 1
rv -= 1
}
}
if (l < rv) sort(l, rv)
if (rv < r) sort(lv, r)
}
sort(0, array.length - 1)
}
def qSortArray3(xs: Array[Int]): Array[Int] ={
if (xs.length <= 1){
xs
}else {
val pivot = xs(xs.length / 2)
val left = xs filter (pivot > _)
val cu = xs filter (pivot == _ )
val right = xs filter (pivot < _ )
Array.concat(
qSortArray3(left),cu,qSortArray3(right))
}
}
def qSortArray4(array: Array[Int]): Array[Int] ={
if (array.length <= 1){
array
}else {
val head = array(0)
val (left,right) = array.tail partition (_ < head )
Array.concat(qSortArray4(left),Array(head),qSortArray4(right))
}
}
}
测试结果
qSortList
-2147483293,-2147483096,-2147481318,-2147480959,-2147479572,-2147479284,-2147478285,-2147477579,-2147476191,-2147475936,
use time : 28808Sorting.quickSort
-2147483293,-2147483096,-2147481318,-2147480959,-2147479572,-2147479284,-2147478285,-2147477579,-2147476191,-2147475936,
use time : 773qSortArray1
-2147483293,-2147483096,-2147481318,-2147480959,-2147479572,-2147479284,-2147478285,-2147477579,-2147476191,-2147475936,
use time : 1335qSortArray2
-2147483293,-2147483096,-2147481318,-2147480959,-2147479572,-2147479284,-2147478285,-2147477579,-2147476191,-2147475936,
use time : 629qSortArray3
508128328,554399267,876118465,968407914,1274954088,1550124974,296879812,2125832312,1874291320,965362519,
use time : 10617qSortArray4
865409973,-645195021,-735017922,-1893119148,1838343395,1038029591,-560471115,-182627393,-228613831,220531987,
use time : 6904
Process finished with exit code 0
环境:版本Scala2.12.6 , win10 ,ryzen5 1600 , 8G
以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。