大數據spark常見面試題匯總(一)

blank

大數據spark常見面試題匯總(一)

1、Spark中的RDD是什麼,有哪些特性

概念:RDD(Resilient Distributed Dataset)叫做彈性分佈式數據集,是Spark中最基本的數據抽象,它代表一個不可變、可分區、裡面的元素可並行計算的集合。

Dataset:就是一個集合,用於存放數據的

Distributed:分佈式,可以並行在集群計算

Resilient:表示彈性的

彈性表示:

1、RDD中的數據可以存儲在內存或者是磁盤

2、RDD中的分區是可以改變的

五大特性:

A list of partitions

一個分區列表,RDD中的數據都存在一個分區列表裡面

A function for computing each split

作用在每一個分區中的函數

A list of dependencies on other RDDs

一個RDD依賴於其他多個RDD,這個點很重要,RDD的容錯機制就是依據這個特性而來的

Optionally, a Partitioner for key-value RDDs (eg to say that the RDD is hash-partitioned)

可選的,針對於kv類型的RDD才具有這個特性,作用是決定了數據的來源以及數據處理後的去向

Optionally, a list of preferred locations to compute each split on (eg block locations for an HDFS file)

可選項,數據本地性,數據位置最優

2、概述一下spark中的常用算子區別(map、mapPartitions、foreach、foreachPartition)

map:用於遍歷RDD,將函數f應用於每一個元素,返回新的RDD(transformation算子)。

foreach:用於遍歷RDD,將函數f應用於每一個元素,無返回值(action算子)。

mapPartitions:用於遍歷操作RDD中的每一個分區,返回生成一個新的RDD(transformation算子)。

foreachPartition: 用於遍歷操作RDD中的每一個分區。無返回值(action算子)。

總結:一般使用mapPartitions或者foreachPartition算子比map和foreach更加高效,推薦使用。

3、談談spark中的寬窄依賴

RDD和它依賴的父RDD(s)的關係有兩種不同的類型,即窄依賴(narrow dependency)和寬依賴(wide dependency)。

寬依賴:指的是多個子RDD的Partition會依賴同一個父RDD的Partition

指子RDD的分區依賴於父RDD的所有分區,這是因為shuffle類操作,如圖中的groupByKey和未經協同劃分的join。

窄依賴:指的是每一個父RDD的Partition最多被子RDD的一個Partition使用。

指父RDD的每一個分區最多被一個子RDD的分區所用,表現為一個父RDD的分區對應於一個子RDD的分區,和兩個父RDD的分區對應於一個子RDD 的分區。 map/filter和union屬於第一類,對輸入進行協同劃分(co-partitioned)的join屬於第二類。

4、spark中如何劃分stage

1、Spark Application中可以因為不同的Action觸發眾多的job,一個Application中可以有很多的job,每個job是由一個或者多個Stage構成的,後面的Stage依賴於前面的Stage,也就是說只有前面依賴的Stage計算完畢後,後面的Stage才會運行。

2、Stage劃分的依據就是寬依賴,何時產生寬依賴,例如reduceByKey,groupByKey的算子,會導致寬依賴的產生。

3、由Action(例如collect)導致了SparkContext.runJob的執行,最終導致了DAGScheduler中的submitJob的執行,其核心是通過發送一個case class JobSubmitted對像給eventProcessLoop。 eventProcessLoop是DAGSchedulerEventProcessLoop的具體實例,而DAGSchedulerEventProcessLoop是eventLoop的子類,具體實現EventLoop的onReceive方法,onReceive方法轉過來回調doOnReceive

4、在handleJobSubmitted中首先創建finalStage,創建finalStage時候會建立父Stage的依賴鏈條

以上是從代碼的邏輯層面上來展開說的,可以簡單點說:先介紹什麼是RDD中的寬窄依賴,然後在根據DAG有向無環圖進行劃分,從當前job的最後一個算子往前推,遇到寬依賴,那麼當前在這個批次中的所有算子操作都劃分成一個stage,然後繼續按照這種方式在繼續往前推,如在遇到寬依賴,又劃分成一個stage,一直到最前面的一個算子。最後整個job會被劃分成多個stage,而stage之間又存在依賴關係,後面的stage依賴於前面的stage。

spark劃分stage的整體思路是:從後往前推,遇到寬依賴就斷開,劃分為一個stage;遇到窄依賴就將這個RDD加入該stage中。

在spark中,Task的類型分為2種:ShuffleMapTask和ResultTask;簡單來說,DAG的最後一個階段會為每個結果的partition生成一個ResultTask,即每個Stage裡面的Task的數量是由該Stage中最後一個RDD的Partition的數量所決定的!而其餘所有階段都會生成ShuffleMapTask;之所以稱之為ShuffleMapTask是因為它需要將自己的計算結果通過shuffle到下一個stage中

map,filtre為窄依賴, groupbykey為寬依賴,遇到一個寬依賴就分一個stage

5、spark-submit的時候如何引入外部jar包

在通過spark-submit提交任務時,可以通過添加配置參數來指定

–driver-class-path 外部jar包

–jars 外部jar包

6、spark 如何防止內存溢出

driver端的內存溢出

可以增大driver的內存參數:spark.driver.memory

這個參數用來設置Driver的內存。在Spark程序中,SparkContext,DAGScheduler都是運行在Driver端的。對應rdd的Stage切分也是在Driver端運行,如果用戶自己寫的程序有過多的步驟,切分出過多的Stage,這部分訊息消耗的是Driver的內存,這個時候就需要調大Driver的內存。

map過程產生大量對象導致內存溢出

這種溢出的原因是在單個map中產生了大量的對象導致的,例如:針對這種問題,在不增加內存的情況下,可以通過減少每個Task的大小,以便達到每個Task即使產生大量的對象Executor的內存也能夠裝得下。具體做法可以在會產生大量對象的map操作之前調用repartition方法,分區成更小的塊傳入map。例如:rdd.repartition(10000).map(x=>for(i <- 1 to 10000) yield i.toString)。

面對這種問題註意,不能使用rdd.coalesce方法,這個方法只能減少分區,不能增加分區,不會有shuffle的過程。

數據不平衡導致內存溢出

數據不平衡除了有可能導致內存溢出外,也有可能導致性能的問題,解決方法和上面說的類似,就是調用repartition重新分區。

shuffle後內存溢出

shuffle內存溢出的情況可以說都是shuffle後,單個文件過大導致的。在Spark中,join,reduceByKey這一類型的過程,都會有shuffle的過程,在shuffle的使用,需要傳入一個partitioner,大部分Spark中的shuffle操作,默認的partitioner都是HashPatitioner,默認值是父RDD中最大的分區數,這個參數通過spark.default.parallelism控制(在spark-sql中用spark.sql.shuffle.partitions) , spark.default.parallelism參數只對HashPartitioner有效,所以如果是別的Partitioner或者自己實現的Partitioner就不能使用spark.default.parallelism這個參數來控制shuffle的並發量了。如果是別的partitioner導致的shuffle內存溢出,就需要從partitioner的代碼增加partitions的數量。

standalone模式下資源分配不均勻導致內存溢出

在standalone的模式下如果配置了–total-executor-cores 和–executor-memory 這兩個參數,但是沒有配置–executor-cores這個參數的話,就有可能導致,每個Executor的memory是一樣的,但是cores的數量不同,那麼在cores數量多的Executor中,由於能夠同時執行多個Task,就容易導致內存溢出的情況。這種情況的解決方法就是同時配置–executor-cores或者spark.executor.cores參數,確保Executor資源分配均勻。使用rdd.persist(StorageLevel.MEMORY_AND_DISK_SER)代替rdd.cache()。 rdd.cache()和rdd.persist(Storage.MEMORY_ONLY)是等價的,在內存不足的時候rdd.cache()的數據會丟失,再次使用的時候會重算,而rdd.persist(StorageLevel.MEMORY_AND_DISK_SER)在內存不足的時候會存儲在磁盤,避免重算,只是消耗點IO時間。

7、spark中cache和persist的區別

cache:緩存數據,默認是緩存在內存中,其本質還是調用persist

persist:緩存數據,有豐富的數據緩存策略。數據可以保存在內存也可以保存在磁盤中,使用的時候指定對應的緩存級別就可以了。

8、簡要描述Spark分佈式集群搭建的步驟

準備:

集群規劃和硬件環境準備

版本選擇

依賴環境準備

模式:

偽分佈式(生產環境不會考慮)

分佈式(現已基本淘汰)

高可用分佈式集群(分佈較廣)

具體步驟:

搭建好hadoop集群

搭建好zookeeper集群

準備安裝安裝包(從官網下載安裝包,或者下載源碼包自行編譯)

解壓縮到對應的安裝目錄

修改配置文件

分發安裝包到所有節點

配置環境變量

啟動集群

驗證集群是否正常運行

9、spark中的數據傾斜的現象、原因、後果

(1)、數據傾斜的現象

多數task執行速度較快,少數task執行時間非常長,或者等待很長時間後提示你內存不足,執行失敗。

(2)、數據傾斜的原因

數據問題

1、key本身分佈不均衡(包括大量的key為空)

2、key的設置不合理

spark使用問題

1、shuffle時的並發度不夠

2、計算方式有誤

(3)、數據傾斜的後果

1、spark中的stage的執行時間受限於最後那個執行完成的task,因此運行緩慢的任務會拖垮整個程序的運行速度(分佈式程序運行的速度是由最慢的那個task決定的)。

2、過多的數據在同一個task中運行,將會把executor撐爆。

10、如何解決spark中的數據傾斜問題

發現數據傾斜的時候,不要急於提高executor的資源,修改參數或是修改程序,首先要檢查數據本身,是否存在異常數據。

(1)、數據問題造成的數據傾斜

找出異常的key,如果任務長時間卡在最後最後1個(幾個)任務,首先要對key進行抽樣分析,判斷是哪些key造成的。

選取key,對數據進行抽樣,統計出現的次數,根據出現次數大小排序取出前幾個。

比如:

如果發現多數數據分佈都較為平均,而個別數據比其他數據大上若干個數量級,則說明發生了數據傾斜。

經過分析,傾斜的數據主要有以下三種情況:

1、null(空值)或是一些無意義的訊息之類的,大多是這個原因引起。

2、無效數據,大量重複的測試數據或是對結果影響不大的有效數據。

3、有效數據,業務導致的正常數據分佈。

解決辦法

第1,2種情況,直接對數據進行過濾即可(因為該數據對當前業務不會產生影響)。

第3種情況則需要進行一些特殊操作,常見的有以下幾種做法

(1) 隔離執行,將異常的key過濾出來單獨處理,最後與正常數據的處理結果進行union操作。

(2) 對key先添加隨機值,進行操作後,去掉隨機值,再進行一次操作。

(3) 使用reduceByKey 代替groupByKey(reduceByKey用於對每個key對應的多個value進行merge操作,最重要的是它能夠在本地先進行merge操作,並且merge操作可以通過函數自定義.)

(4) 使用map join。

案例:

如果使用reduceByKey因為數據傾斜造成運行失敗的問題。具體操作流程如下:

(1) 將原始的key 轉化為key + 隨機值(例如Random.nextInt)

(2) 對數據進行reduceByKey(func)

(3) 將key + 隨機值轉成key

(4) 再對數據進行reduceByKey(func)

案例操作流程分析:

假設說有傾斜的Key,我們給所有的Key加上一個隨機數,然後進行reduceByKey操作;此時同一個Key會有不同的隨機數前綴,在進行reduceByKey操作的時候原來的一個非常大的傾斜的Key就分而治之變成若干個更小的Key,不過此時結果和原來不一樣,怎麼破?進行map操作,目的是把隨機數前綴去掉,然後再次進行reduceByKey操作。

注意1: 如果此時依舊存在問題,建議篩選出傾斜的數據單獨處理。最後將這份數據與正常的數據進行union即可。

注意2: 單獨處理異常數據時,可以配合使用Map Join解決。

(2)、Spark使用不當造成的數據傾斜

提高shuffle並行度

dataFrame和sparkSql可以設置spark.sql.shuffle.partitions參數控制shuffle的並發度,默認為200。

rdd操作可以設置spark.default.parallelism控制並發度,默認參數由不同的Cluster Manager控制。

局限性: 只是讓每個task執行更少的不同的key。無法解決個別key特別大的情況造成的傾斜,如果某些key的大小非常大,即使一個task單獨執行它,也會受到數據傾斜的困擾。

使用map join 代替reduce join

在小表不是特別大(取決於你的executor大小)的情況下使用,可以使程序避免shuffle的過程,自然也就沒有數據傾斜的困擾了.

局限性: 因為是先將小數據發送到每個executor上,所以數據量不能太大。

11、利用scala語言實現排序

(1)冒泡排序

class BubbleSort { class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } def main(args: Array[String]): Unit = { class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } val list = List(3, 12, 43, 23, 7, 1, 2, 0) class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } println(sort(list)) class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } } class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } //定義一個方法,傳入的參數是要進行排序的List集合,輸出的是排序後的List集合def sort(list: List[Int]): List[Int] = list match { class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } case List() => List() class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } case head :: tail => compute(head, sort(tail)) class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } } class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } case List() => List(data) class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } } } class BubbleSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(sort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def sort(list: List[Int]): List[Int] = list match { case List() => List() case head :: tail => compute(head, sort(tail)) } def compute(data: Int, dataSet: List[Int]): List[Int] = dataSet match { case List() => List(data) case head :: tail => if (data <= head) data :: dataSet else * head :: compute(data, tail) } }

(2)快速排序

object QuickSort { object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } def main(args: Array[String]): Unit = { object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } val list = List(3, 12, 43, 23, 7, 1, 2, 0) object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } println(quickSort(list)) object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } } object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } //定義一個方法,傳入的參數是要進行排序的List集合,輸出的是排序後的List集合def quickSort(list: List[Int]): List[Int] = { object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } //對輸入參數list進行模式匹配list match { object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } case Nil => Nil object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } case List() => List() object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } case head :: tail => object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } val (left, right) = tail.partition(_ < head) object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } quickSort(left) ++ (head :: quickSort(right)) object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } } object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } } } object QuickSort { def main(args: Array[String]): Unit = { val list = List(3, 12, 43, 23, 7, 1, 2, 0) println(quickSort(list)) } //定义一个方法,传入的参数是要进行排序的List集合,输出的是排序后的List集合def quickSort(list: List[Int]): List[Int] = { //对输入参数list进行模式匹配list match { case Nil => Nil case List() => List() case head :: tail => val (left, right) = tail.partition(_ < head) quickSort(left) ++ (head :: quickSort(right)) } } }

What do you think?

Written by marketer

SCI論文的討論部分加分句型

blank

外貿小公司、小工廠如何接外貿訂單?