これが Scala の真髄です。これを受講すれば、面接を恐れることはありません。

これが Scala の真髄です。これを受講すれば、面接を恐れることはありません。

[[427956]]

この記事はWeChatの公開アカウント「ビッグデータ左右手」から転載したもので、著者はZuoyouです。この記事を転載する場合は、Big Data Left and Right Hand の公開アカウントにご連絡ください。

序文

オブジェクト指向の関数型プログラミング言語である Scala は、オブジェクト指向プログラミングと関数型プログラミングを組み合わせて、コードをより簡潔で効率的かつ理解しやすいものにします。これが Scala が人気を博した理由です。

Scala は JVM 言語です。ビッグデータ エコシステムのほとんどのコンポーネントは Java で開発されており、Scala は Java とシームレスに混合できるため、ビッグデータ エコシステムにうまく統合できます。

メインコンテンツ

開発環境、ループ、例外、ジェネリックなどの基本的なものは記載されなくなります。この記事では、概念の理解と使用方法に重点を置いて、独自の特別なエッセンスのみを紹介します。

1. 変数とデータ型

2. 関数型プログラミング

(a) 高階関数

(b) 匿名関数

(c)閉鎖

(d) 関数カリー化

3. オブジェクト指向

(a) クラスとオブジェクト

(b) コンパニオンオブジェクト

(c)特徴

4. パターンマッチング

5. 暗黙的な変換

変数とデータ型

変数(var は変数を宣言し、val は定数を宣言します)

var修飾子変数は変更可能です

val によって変更された変数は変更できません

しかし、本当にそうなのでしょうか?

以下の定義について

  1. クラスA(a: Int ) {
  2. var 値 = a
  3. }
  4.  
  5. クラスB(b: Int ) {
  6. val値 = 新しいA(b)
  7. }

効果テスト

  1. val x = 新しいB(1)
  2.  
  3. x = new B(1) // エラー。x は val によって変更されており、参照は変更できないため
  4. x.value = new A(1) // エラー。x.value は val によって変更されており、参照は変更できないため
  5.  
  6. x.value.value = 1 // 正解、x.value.valueはvarによって変更され、再割り当てできます

実際、var によって変更されたオブジェクト参照は変更できますが、val によって変更されたオブジェクト参照は変更できませんが、オブジェクトの状態は変更できます。

可変性と不変性の理解

Scala の List は不変であり、Map は可変と不変の両方であることがわかっています。次の例を見てください

var mutable と List immutable の組み合わせ

  1. var list = List( "左" , "右" )
  2.  
  3. リスト += "手"  

理解とは

var list が指すオブジェクトは List("left","right") です。

後でリストが変更されます。変数var修飾子なので、リストは新しいリスト(「left」、「right」、「hand」)を指すことができます。

以下の場合(エラーを報告します)

  1. val list = List( "左" , "右" )
  2.  
  3. リスト += "手"  

val var と Map の可変と不変

  1. var map = マップ(
  2. 「左」 -> 1、
  3. 「右」 ->1、
  4. map+=( "手" ->1)
  1. val map=scala.collection.mutable.Map(
  2. 「左」 -> 1、
  3. 「右」 ->1、
  4.  
  5. map+=( "手" ->1)

理解する

不変のマップに要素を追加すると、元のマップは変更されず、元のマップと追加された要素を保存するために新しいマップが生成されます。

変更可能なマップに要素を追加する場合、新しいマップは生成されず、要素は元のマップに直接追加されます。

val に関して不変なのはポインターのみであり、これはオブジェクト マップとは関係ありません。

データ型

データ型説明する
バイト 8 ビットの符号付き 2 の補数整数。値の範囲は-128~127です
短い 16 ビットの符号付き 2 の補数整数。値の範囲は-32768~32767です
中級 32 ビットの符号付き 2 の補数整数。値の範囲は -2147483648 ~ 2147483647 です
長さ 64 ビットの符号付き 2 の補数整数。値の範囲は -9223372036854775808 から 9223372036854775807 です。
フロート 32 ビット、IEEE 754 標準単精度浮動小数点数
ダブル 64 ビット IEEE 754 標準倍精度浮動小数点数
チャー 16 ビットの符号なし Unicode 文字、範囲の値は U+0000 から U+FFFF です。
文字列
ブール真実か偽か
ユニット値がないことを表します。他の言語の void に相当します。結果を返さないメソッドの結果タイプとして使用されます。ユニットには、() として記述されるインスタンス値が 1 つだけあります。
ヌル null または空の参照
何もない Nothing 型は Scala のクラス階層の最下部にあります。それは他のすべてのタイプのサブタイプです。
どれでも Anyは他のすべてのクラスのスーパークラスです
任意の参照 AnyRef クラスは、Scala のすべての参照クラスの基本クラスです。

関数型プログラミング

高階関数

高階関数とは、他の関数をパラメータとして受け取ったり、結果として関数を返したりする関数です。関数は Scala の第一級オブジェクトです。

簡単な例

  1. val リスト = リスト (1,2,3,4)
  2.  
  3. val関数= (x: Int ) => x*2
  4.  
  5. val 値=list.map(関数)

関数としてのメソッド

  1. def main(args: Array[String]): 単位 = {
  2. val リスト = リスト (1,2,3,4)
  3. val 値=list.map(関数)
  4. }
  5.  
  6. def関数(x: Int )=x*2

関数を返す関数

  1. def calculate(シンボル:文字列): (文字列,文字列)=>文字列 ={
  2. シンボルマッチ {
  3. 場合  "スプライシング方法 1" => (a:String,b:String)=> s "スプライシング方法 1:$a,$b"  
  4. 場合  「連結方法 2」 => (a:String,b:String)=> s 「連結方法 2: $b 、 $a」  
  5. }
  6. }
  1. val関数: (String, String) => String = calculate( "スプライシング方法 2" )
  2.  
  3. println(関数( "ビッグデータ" "左手と右手" ))

匿名関数

Scala で匿名関数を定義する構文は非常にシンプルで、矢印の左側にパラメータ リスト、右側に関数本体が配置されます。

匿名関数を使用すると、コードはより簡潔になります。

  1. var inc = (x: Int ) => x+1 です。
  2.  
  3. var x = inc(7)-1

パラメータなしも可能

  1. var user = () => println( "ビッグデータの右手" )

閉鎖

クロージャは、戻り値が関数外で宣言された 1 つ以上の変数に依存する関数です。

クロージャは一般に、関数内のローカル変数にアクセスできる別の関数と考えることができます。

簡単に言えば、関数内の変数がそのスコープ内にない場合でも、外部からアクセスできるということです。

  1. val関数= (x: Int ) => x*2

クロージャの本質は、コードと非ローカル変数の混合である。

クロージャ = コード + 使用される非ローカル変数

  1. val 事実 = 2
  2. val関数= (x: Int ) => x*fact

関数カリー化

カリー化とは、もともと 2 つのパラメータを受け入れる関数を、 1 つのパラメータを受け入れる新しい関数に変換するプロセスを指します。新しい関数は、元の 2 番目の引数を引数として受け取る関数を返します。

まず簡単な

  1. def add (x: Int ,y: Int )=x+y
  2.  
  3. 使用
  4.  
  5. (1,2)を加える

関数変換(この方法はカリー化と呼ばれます)

  1. def add (x: Int ,y: Int )=x+y
  2.  
  3. 使用
  4.  
  5. (1,2)を加える

実装プロセス

add(1)(2)は実際には2つの通常の関数(非カリー化関数)を順番に呼び出します。

最初の呼び出しは 1 つの引数 x を受け取り、関数型の値を返します。

2 回目にこの関数が呼び出されるときは、パラメータ y の値が使用されます。

  1. xをパラメータとして受け取り、無名関数を返す
  2.  
  3. Intパラメータ y を受け取り、関数本体は x+y です。
  4.  
  5. def add (x: Int )=(y: Int )=>x+y
  6.  
  7. (1)
  8. val result = add (1) // 結果= (y: Int )=>1+y
  9.  
  10. (2)
  11. val合計= 結果(2)
  12.  
  13. (3)
  14. 合計= 3

オブジェクト指向

クラスとオブジェクト

クラスはオブジェクトの抽象化であり、オブジェクトはクラスの具体的なインスタンスです。クラスは抽象的でありメモリを占有しませんが、オブジェクトは具体的でありストレージスペースを占有します。クラスはオブジェクトを作成するための設計図です。特定のタイプのオブジェクトに含まれるメソッドと変数を定義するソフトウェア テンプレートです。

クラスにはクラスパラメータがある

クラス パラメータはクラスの本体内で直接使用できます。クラス パラメータには var というプレフィックスを付けることもでき、private、protected、override を使用して変更することもできます。 Scala コンパイラはクラス パラメータを収集し、同じパラメータを持つクラスのプライマリ コンストラクターを作成します。 、フィールドでもメソッド定義でもないクラス内のすべてのコードをプライマリ コンストラクターにコンパイルします。

  1. クラスTest(val a: Int , val b: Int ) {
  2. //
  3. }

例クラス

ケース クラスは通常、パターン マッチング用に最適化できる特別なクラスであるサンプル クラスに変換されます。

クラスがケースクラスとして宣言されている場合。以下の機能があります:

  1. コンストラクター内のパラメーターが var として宣言されていない場合は、デフォルトで val 型になります。
  2. コンパニオン オブジェクトを自動的に作成し、その中にサブ適用メソッドを実装して、使用時に new を使用してオブジェクトを直接作成する必要がないようにしました。
  3. コンパニオン オブジェクトは、ケース クラスをパターン マッチングに適用できるように、unapply メソッドを実装するのにも役立ちます。
  4. 独自のtoString、hashCode、copy、equalsメソッドを実装する
  1. ケースクラス人(
  2. 名前:文字列、
  3. 年齢: 

オブジェクトとコンパニオンオブジェクト

Scala シングルトン オブジェクトは非常に重要です。 Java とは異なり、静的クラス、静的メンバー、静的メソッドはありませんが、Scala はオブジェクト オブジェクトを提供します。このオブジェクトは Java の静的クラスに似ています。デフォルトでは、そのメンバーとメソッドは静的です。

シングルトン オブジェクトを定義することはクラスを定義することを意味しないため、それを使用して新しいオブジェクトを作成することはできません。シングルトン オブジェクトがクラスと同じ名前を共有する場合、そのオブジェクトはクラスのコンパニオン オブジェクトと呼ばれます。

クラスとそのコンパニオン オブジェクトは同じソース ファイルで定義する必要があります。このクラスは、このシングルトン オブジェクトのコンパニオン クラスと呼ばれます。

クラスとそのコンパニオン オブジェクトは、互いのプライベート メンバーにアクセスできます。

  1. オブジェクトテスト{
  2. プライベート変数= "ビッグデータ"  
  3.  
  4. def main(args: Array[String]): 単位 = {
  5. valテスト = 新しいテスト()
  6. println(テスト名を更新します())
  7. }
  8. }
  9.  
  10. クラステスト{
  11. def update_name(): 文字列 = {
  12. テスト。 name = "左手と右手"  
  13. テスト名 
  14. }
  15.  
  16. }

特性

Scala のトレイトは Java のインターフェースと同等ですが、実際にはインターフェースよりも強力です。インターフェースとは異なり、プロパティとメソッドの実装も定義できます。

通常、Scala クラスは単一の親クラスからのみ継承できますが、特性の場合は複数の親クラスから継承できます。その結果、多重継承が実装されます(キーワード with)。実際、Scala の特性は Java の抽象クラスに似ています。

  1. オブジェクト Test は UserImp をAddressImp拡張します{
  2. def getUserName() をオーバーライドします: String = ???
  3.  
  4. def getAddress() をオーバーライドします: String = ???
  5. }
  6.  
  7. 特性 UserImp{
  8. def getUserName():文字列
  9. }
  10.  
  11. 特性アドレスImp{
  12. デフgetAddress():文字列
  13. }

パターンマッチング

Java の switch を例に挙げてみましょう。 Java の switch は、いくつかの基本的な型マッチングのみを実行し、いくつかのアクションを実行しますが、戻り値はありません。

Scala のパターン マッチングははるかに強力です。値の一致に加えて、型の一致も可能です。

  1. def calculate(シンボル:文字列): (文字列,文字列)=>文字列 ={
  2. シンボルマッチ {
  3. 場合  "スプライシング方法 1" => (a:String,b:String)=> s "スプライシング方法 1:$a,$b"  
  4. 場合  「連結方法 2」 => (a:String,b:String)=> s 「連結方法 2: $b 、 $a」  
  5. }
  6. }

私が驚いたのは(ほんの数行ですが)

  1. クイックソート
  2.  
  3. def quickSort(list: List[ Int ]): List[ Int ] = リストの一致 {
  4. ケースNil => Nil
  5. ケースリスト() => リスト()
  6. ケースヘッド :: テール =>
  7. val ( left , right ) = tail.partition(_ < head)
  8. クイックソート() ::: ヘッド :: クイックソート()
  9. }
  10.    
  11. マージ
  12.  
  13. def merge(: List[ Int ],: List[ Int ]): List[ Int ] = (,) 一致 {
  14. case (Nil, _) =>正しい 
  15. case (_, Nil) => 
  16. ケース(x::xTail, y::yTail) =>
  17. x <= y の場合、 x :: merge(xTail, right )
  18. そうでない場合はy :: merge( left , yTail)
  19. }

暗黙的な変換

Scala が提供する暗黙的な変換と暗黙的なパラメータ関数は非常に特徴的な機能です。これはJavaなどのプログラミング言語にはない機能です。特定のタイプのオブジェクトを別のタイプのオブジェクトに変換するように手動で指定できます。これらの機能を通じて、非常に強力で特別な機能を実現できます。

ルール

(1)暗黙的な変換を使用する前に、importを使用して現在のスコープへの暗黙的な変換を参照するか、スコープ内で暗黙的な変換を定義する必要があります。

(2)暗黙的な変換は、他の変換が利用できない場合にのみ実行できます。同じスコープ内の同じソース タイプに対して複数の暗黙的な変換関数が定義されている場合、複数の暗黙的な変換関数が一致する可能性があるとコンパイラはエラーを報告します。そのため、使用時には不要な暗黙的な定義を削除してください。

暗黙的なデータ型の変換

String 型は Int 型に自動的に変換できないため、String 型の値を Int 型の変数または定数に割り当てると、コンパイラはエラーを報告します。しかし.....

  1. 暗黙的な def strToInt(str: String) = str.toInt
  2. def main(args: Array[String]): 単位 = {
  3. 値 a: Int = "100"  
  4.    
  5. 印刷(a)
  6. }

パラメータの暗黙的な変換

いわゆる暗黙のパラメータとは、関数またはメソッド内で implicit によって変更されるパラメータを指します。このとき、Scala は、暗黙の値、つまり暗黙の値で変更された指定された型のオブジェクトを見つけて、パラメータを注入しようとします。

  1. オブジェクトテスト{
  2. プライベート変数= "ビッグデータ"  
  3. 暗黙の val test = new Test
  4.  
  5. def getName(暗黙のテスト:テスト): ユニット ={
  6. println(テスト名を更新します())
  7. }
  8. def main(args: Array[String]): 単位 = {
  9. 名前を取得する
  10. }
  11. }
  12.  
  13. クラステスト{
  14. def update_name(): 文字列 = {
  15. テスト。 name = "左手と右手"  
  16. テスト名 
  17. }
  18.  
  19. }

<<:  マルチクラウドおよびハイブリッドクラウドシナリオにおけるデータ同期ソリューション: Kafka

>>:  クラウドネイティブアプリケーションを保護する方法

推薦する

アンカーテキストは消え去り、プレーンテキストリンクの時代が到来

外部リンクの構築は日常的な問題ですが、私たちの日々の仕事の焦点でもあります。しかし、現在SEOに取り...

ウェブサイトのランキング向上におけるタイトルタグの役割

タイトルの書き方A:タイトルタグは、ウェブサイトのランキングを向上させる上で非常に重要な役割を果たし...

Dogyun:「香港-KC」データセンターの「BGPライン」VPSの簡単なレビュー

GouCloud 香港 KC データセンターの VPS の複数の回線が提供する帯域幅は異なります。帯...

インターネットプロモーションプラン:企業サイトのランキングを上げるには?

月収10万元の起業の夢を実現するミニプログラム起業支援プラン企業のマーケティング担当者は、日々インタ...

#BlackFive# メガレイヤー: 香港/フィリピン/シンガポール/アメリカ、VPS は年間 199 元から、専用サーバーは月額 299 元から

Megalayer は今年のブラックフライデー プロモーションを開始しました。香港 (中国)、マニラ...

クラウドではなくエッジ コンピューティングを選択すべきなのはどのような場合ですか?

モノのインターネットの台頭は驚異的でした。 2030 年までに、世界中で接続される IoT デバイス...

建武大学卒業生の「美人コンテスト」ウェブサイトのハッキングは著作権侵害に当たる

写真は「武漢美人コンテスト」ウェブサイトのスクリーンショット。本紙(記者ドゥ・アンナ、インターン生フ...

ローカルポータルサイトの最適化提案

タイトルを「最適化計画」ではなく「最適化提案」としたのは、地域ポータルサイトの形態が多様であり、シス...

Xiaomiの成功物語: 80/20ルールと心理マーケティングの完璧な応用

「愛好家のために生まれた」は Xiaomi のスロ​​ーガンです。Xiaomi が設立から市場で大き...

Yecao Cloud - ロサンゼルス高速VPSシンプルレビュー/ceranetworksデータセンター

Yecao Cloud (旧称 Yecao Host)は 2009 年に設立され、Fuqing Li...

A5 Yuehuai SEO最適化道路の分析

最近のSEOニュースを調べてみると、A5が正式に独立したドメイン名yuehuai.comを立ち上げ、...

「Baiduホームページに追加」ボタンに関するいくつかの疑問に対する私の個人的な意見

注意しないと、Baidu には実際にいくつかのサイトの下に「Baidu ホームページに追加」というボ...

浙江省がオンラインショッピングのねずみ講を再び調査:多くのリベートサイトが次々と倒産

浙江省、総額287億元のオンラインショッピングねずみ講を再度調査こうしたウェブサイトは次々と崩壊して...

Xigua Video は Bilibili と競争するために何を使用できますか?

愛情を込めて電気を作るのは、食事を食べるほど美味しくないというのは本当でしょうか?私はそうは思わない...