经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » Java相关 » Scala » 查看文章
Scala中Array和List的区别说明
来源:jb51  时间:2021/10/11 10:23:42  对本文有异议

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数组效率实测

代码

  1. package com.tingfeng.scala.test
  2. import scala.annotation.tailrec
  3. import scala.util.{Random, Sorting}
  4. /**
  5. * 快速排序测试
  6. */
  7. object SortTest {
  8. /**
  9. * 初始化一个数组,产生随机数字填充
  10. * @param size
  11. * @return
  12. */
  13. def initRandomList(size :Int):List[Int]={
  14. val random = new Random()
  15. def initList(size :Int,random: Random):List[Int] = size match {
  16. case 0 => Nil
  17. case 1 => List(random.nextInt())
  18. case s:Int =>
  19. val value = s / 2
  20. if( s % 2 == 0) {
  21. initList(value,random) ++ initList(value,random)
  22. }else{
  23. initList(value,random) ++ initList(value + 1,random)
  24. }
  25. }
  26. initList(size,random)
  27. }
  28. /**
  29. * 打印出使用的时间
  30. * @param call
  31. */
  32. def printTime(call : => Unit,tag: String = ""){
  33. val startTime = System.currentTimeMillis()
  34. println(tag)
  35. call
  36. println
  37. println(s"use time : ${System.currentTimeMillis() - startTime}\n")
  38. }
  39. /**
  40. * 交换数组中两个位置的值,经过测试这种按位与的方式比普通建立变量交换的效率更高
  41. * @param array
  42. * @param x
  43. * @param y
  44. */
  45. def swap(array: Array[Int],x:Int,y:Int):Unit ={
  46. val t = array(x) ^ array(y)
  47. array(x) = t ^ array(x)
  48. array(y) = t ^ array(y)
  49. }
  50. /**
  51. * 将传入的值直接返回,并且执行逻辑
  52. * @param call
  53. * @param any
  54. * @tparam A
  55. */
  56. def doThing[A<:Any](any: A,call: A => Unit):A = {
  57. call(any)
  58. any
  59. }
  60. /**
  61. * 打印列表
  62. */
  63. def printList[A<%Seq[Any]](seq:A,size :Int = 10):Unit={
  64. seq.splitAt(size)._1.foreach(it => print(s"$it,"))
  65. }
  66. def shuffleIntSeq(seq: Array[Int],size: Int):Unit={
  67. val random = new Random()
  68. val maxSize = size/2
  69. for(i <- 0 to maxSize){
  70. swap(seq,i,maxSize + random.nextInt(maxSize))
  71. }
  72. }
  73. def main(args: Array[String]): Unit = {
  74. val size = 5000000
  75. val printSize = 10
  76. val list = initRandomList(size)
  77. //打印出钱100个,和List快速排序的时间花费
  78. printTime(printList[List[Int]](qSortList(list),Math.min(10,size)),"qSortList")
  79. val array = list.toArray
  80. printTime(printList[Array[Int]](doThing[Array[Int]](array,Sorting.quickSort),Math.min(printSize,size)),"Sorting.quickSort")
  81. shuffleIntSeq(array,size)
  82. printTime(printList[Array[Int]](doThing[Array[Int]](array,qSortArray1),Math.min(printSize,size)),"qSortArray1")
  83. shuffleIntSeq(array,size)
  84. printTime(printList[Array[Int]](doThing[Array[Int]](array,qSortArray2),Math.min(printSize,size)),"qSortArray2")
  85. shuffleIntSeq(array,size)
  86. printTime(printList[Array[Int]](doThing[Array[Int]](array,qSortArray3),Math.min(printSize,size)),"qSortArray3")
  87. shuffleIntSeq(array,size)
  88. printTime(printList[Array[Int]](doThing[Array[Int]](array,qSortArray4),Math.min(printSize,size)),"qSortArray4")
  89. }
  90. /**
  91. * 对List快速排序
  92. * @param list
  93. * @return
  94. */
  95. def qSortList(list: List[Int]):List[Int] = list match {
  96. case Nil => Nil
  97. case head :: other =>
  98. val (left, right) = other.partition(_ < head)
  99. (qSortList(left) :+ head) ++ qSortList(right)
  100. }
  101. /**
  102. * 通过每次比较数组‘head'值与其余值的方式直接实现
  103. * 比‘head'小的值移动到其前,比‘head'大的移动到其之后
  104. * @param array
  105. */
  106. def qSortArray1(array: Array[Int]):Unit = {
  107. def sort(ay : Array[Int],start: Int,end: Int):Unit={
  108. if(start >= end) {
  109. return
  110. }
  111. val head = ay(start)
  112. var spliteIndex = start
  113. for (i <- start + 1 to end){
  114. if(ay(i) < head){
  115. swap(array,spliteIndex,i)
  116. spliteIndex += 1
  117. }
  118. }
  119. if(start != spliteIndex){
  120. sort(ay, start, spliteIndex)
  121. }
  122. if(start == spliteIndex){
  123. spliteIndex += 1
  124. }
  125. if(spliteIndex != end){
  126. sort(ay, spliteIndex, end)
  127. }
  128. }
  129. sort(array,0,array.size - 1)
  130. }
  131. /**
  132. * 将数据以中线拆分左右两部分,交换值,使得右边值比左边大,
  133. * 再以左或者右边交换的界限分为两部分做递归
  134. * @param array
  135. */
  136. def qSortArray2(array: Array[Int]) {
  137. def sort(l: Int, r: Int) {
  138. val pivot = array((l + r) / 2)
  139. var lv = l; var rv = r
  140. while (lv <= rv) {
  141. while (array(lv) < pivot) lv += 1
  142. while (array(rv) > pivot) rv -= 1
  143. if (lv <= rv) {
  144. swap(array,lv, rv)
  145. lv += 1
  146. rv -= 1
  147. }
  148. }
  149. if (l < rv) sort(l, rv)
  150. if (rv < r) sort(lv, r)
  151. }
  152. sort(0, array.length - 1)
  153. }
  154. /**
  155. * 系统自带的过滤函数,无法排序成功,因为filter返回的是引用
  156. * @param xs
  157. * @return
  158. */
  159. def qSortArray3(xs: Array[Int]): Array[Int] ={
  160. if (xs.length <= 1){
  161. xs
  162. }else {
  163. val pivot = xs(xs.length / 2)
  164. val left = xs filter (pivot > _)
  165. val cu = xs filter (pivot == _ )
  166. val right = xs filter (pivot < _ )
  167. Array.concat(
  168. qSortArray3(left),cu,qSortArray3(right))
  169. }
  170. }
  171. /**
  172. * 系统自带的分割函数,无法排序成功,因为partition返回的是引用,数据量大的时候会栈溢出失败
  173. * @param xs
  174. * @return
  175. */
  176. def qSortArray4(array: Array[Int]): Array[Int] ={
  177. if (array.length <= 1){
  178. array
  179. }else {
  180. val head = array(0)
  181. val (left,right) = array.tail partition (_ < head )
  182. Array.concat(qSortArray4(left),Array(head),qSortArray4(right))
  183. }
  184. }
  185. }

测试结果

qSortList
-2147483293,-2147483096,-2147481318,-2147480959,-2147479572,-2147479284,-2147478285,-2147477579,-2147476191,-2147475936,
use time : 28808

Sorting.quickSort
-2147483293,-2147483096,-2147481318,-2147480959,-2147479572,-2147479284,-2147478285,-2147477579,-2147476191,-2147475936,
use time : 773

qSortArray1
-2147483293,-2147483096,-2147481318,-2147480959,-2147479572,-2147479284,-2147478285,-2147477579,-2147476191,-2147475936,
use time : 1335

qSortArray2
-2147483293,-2147483096,-2147481318,-2147480959,-2147479572,-2147479284,-2147478285,-2147477579,-2147476191,-2147475936,
use time : 629

qSortArray3
508128328,554399267,876118465,968407914,1274954088,1550124974,296879812,2125832312,1874291320,965362519,
use time : 10617

qSortArray4
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

以上为个人经验,希望能给大家一个参考,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号