Langage de programmation Scala

Langage de programmation Scala

1. Introduction de Scala

1. Le but de l'apprentissage de Scala

Les cadres technologiques sous-jacents du Big Data tels que Spark et Kafka sont tous écrits dans le langage de programmation Scala. Lorsque nous écrivons nos propres programmes distribués dans Spark, Spark fournit une variété de styles de langage de programmation, mais nous utilisons le plus souvent la programmation Scala.

2. Concepts de base de Scala

  • Scala est une grammaire de programmation multi-paradigme. Le soi-disant multi-paradigme fait référence à la grammaire de plusieurs styles de programmation. Scala est principalement un langage de programmation orienté objet et un langage de programmation fonctionnel.
  • L'inventeur de Scala est Martin Odesky. Le langage Scala est né vers 2001 et intègre de nombreuses fonctionnalités de Java et JS.
  • Dans le même temps, de nombreuses fonctionnalités de Java sont également absorbées par le langage Scala.L'expression lambda dans la version JDK8.0 est absorbée par Scala.
  • Nouvelles fonctionnalités de la version JDK1.8
    • Interface de programmation fonctionnelle, expression lambda, référence de méthode, composition de l'interface, classe d'heure et de date, API Stream, classe facultative (pour résoudre NullPointException) en Java.
    • Interface fonctionnelle : Une interface avec une seule méthode abstraite est appelée une interface fonctionnelle. En général, les interfaces fonctionnelles doivent utiliser @FunctionalInterface
    • L'expression lambda (λ) en Java est étroitement liée à une interface en Java. Interface de programmation fonctionnelle de l'interface (il n'y a qu'une seule méthode abstraite dans l'interface) syntaxe : (liste formelle des paramètres) -> {corps de la méthode ; } Simplification de l'
      expression
      lambda :
      1. Le type de la liste de paramètres formels peut être omis, car la méthode abstraite de l'interface de programmation fonctionnelle correspondant à l'expression lambda est déterminée.
      2. S'il n'y a qu'une seule liste de paramètres, le () dans la liste de paramètres formelle peut être omis.
      3. Si le corps de la méthode n'a qu'une seule ligne de code et que cette ligne de code n'a pas le mot-clé return, alors le {} dans le corps de la méthode peut être omis et il n'est pas nécessaire d'ajouter un point-virgule à cette ligne de code.
    • La référence de méthode en Java équivaut à une version améliorée de l'expression lambda. Elle est principalement utilisée pour remplacer l'expression lambda entière. Lorsque le corps de la méthode de l'expression lambda fait référence à une méthode d'une autre classe, et le corps de la méthode Lorsqu'il n'y a pas de redondance code, vous pouvez utiliser des références de méthode pour simplifier le code.
  • Comment fonctionne Scala
    • Écrivez le fichier de code source xxx.scala. Vous pouvez utiliser le SDK Scala ou le SDK Java dans le fichier de code source.
    • Utilisez Scalac pour compiler le fichier de code source xxx.scala dans le fichier de bytecode binaire Java xxx.class
    • Utilisez la commande scala pour charger xxx.class dans la machine virtuelle Java JVM et l'exécuter

2. Construction de l'environnement Scala

1. Étapes d'installation

Étape 1 : Installez et détectez JDK1.8 ou supérieur.

image-20230911102219866

Étape 2 : Accédez au site officiel de Scala , cliquez sur la version que vous souhaitez télécharger, j'ai téléchargé la 2.13.11, puis cliquez sur la version Windows avec le suffixe .msi pour la télécharger.

image-20230911102519826

image-20230911102858232

Étape 3 : Après le téléchargement en local, double-cliquez scala-2.13.11.msipour installer

image-20230911110019339

image-20230911110133440

Parce que scala n'occupe pas une grande quantité de mémoire et que l'espace de stockage requis n'augmentera pas automatiquement à l'avenir, je l'ai mis sur le lecteur C sans changer la lettre du lecteur.

image-20230911110213768

image-20230911110423400

image-20230911110513668

Étape 4 : L'installation est réussie ! Ouvrez la fenêtre de ligne de commande et entrez la commande scala -versionpour vérifier si l'installation a réussi !

image-20230911110915069

2. Configurer les variables d'environnement

Étape 1 : Poste de travail->Clic droit->Propriétés->Paramètres système avancés->Variables d'environnement

Étape 2 : Créez-en une nouvelle sous la colonne de variable utilisateur -> nom de la variable : SCALA_HOME, et la valeur de la variable est le chemin de l'ordinateur sur lequel scala est installé.

image-20230911111249896

Étape 3 : Configurer les variables de chemin -> Double-cliquez sur Chemin sous les variables utilisateur pour configurer comme indiqué dans la figure

image-20230911111416616

Étape 4 : Assurez-vous de cliquer sur OK sur toutes les options avant de fermer la fenêtre.

3. Tester Scala

Ouvrez la fenêtre de ligne de commande de votre ordinateur et utilisez le REPL (Read Eval Print Loop, interpréteur interactif) de Scala pour effectuer des tests de base de l'environnement.

image-20230911112024458

Les trois premières commandes sont : la syntaxe de Scala pour définir les constantes et les variables, qui sera abordée plus tard ;

La quatrième commande est : le scénario dans lequel une erreur se produit lorsqu'une constante est réaffectée ;

La cinquième commande est la suivante : réaffectez la variable b dont le type de données est Int à zs dont le type de données est chaîne et une erreur se produit.

Explication supplémentaire de l'erreur signalée par la cinquième commande :

  • Scala est un langage fortement typé. Une fois le type de variable déterminé, il ne peut plus être modifié.
  • Un langage fortement typé est un langage qui applique la définition de type. Une fois qu'une variable est définie, ce sera toujours ce type de données si sa conversion n'est pas forcée.
  • Un langage faiblement typé est un langage avec des définitions faiblement typées.Une certaine variable a un type défini et la variable peut être automatiquement convertie en fonction des changements dans l'environnement sans contrainte explicite. Nous pouvons donner un exemple de langage faiblement typé comme suit.

image-20230911113112855

Créez un nouveau fichier HW.scala dans un certain dossier de votre ordinateur et écrivez le contenu. Ensuite, nous utilisons la fenêtre de ligne de commande pour compiler et exécuter.

class HW{
    
    
	
}
object HW{
    
    
  def main(args:Array[String]):Unit={
    
    
     println("HW")
  }
}

image-20230911151411157

Après compilation, deux nouveaux fichiers seront générés

image-20230911151357063

4. Intégration de Scala et de l'idée

Étape 1 : Téléchargez d’abord le plug-in Scala fourni dans l’idée, installez et redémarrez.

image-20230911113533757

Étape 2 : Créez un nouveau projet maven.

image-20230911113415025

Étape 3 : cliquez avec le bouton droit sur le projet, sélectionnez Ajouter un support de framework, cochez la case Scala, puis cliquez sur CRÉER, puis cliquez sur Navigateur... pour sélectionner le chemin d'installation de Scala.

image-20230911142947751

image-20230911143229972

Étape 4 : Créez un nouveau dossier nommé scala pour stocker le code écrit en scala et définissez ce dossier comme racine des sources.

image-20230911143909606

Étape 5 : Écrivez le code Scala

image-20230911144155389

image-20230911150500149

5. Code source associé

Nous téléchargeons le package de code source correspondant à partir du site officiel sur lequel nous venons de télécharger Scala scala-sources-2.13.11.tar.gz, puis décompressons le package compressé dans un répertoire stable local.

image-20230911160218769

image-20230911160833932

6. Description de la classe et de l'objet

Scala est entièrement orienté objet, donc Scala supprime les éléments non orientés objet en Java, tels que le mot clé static et le type void.

  • Scala n'a pas de mot-clé static et l'objet implémente des fonctions similaires aux méthodes statiques (nom de classe. nom de méthode) ; le mot-clé class a la même fonction que le mot-clé class en Java et est utilisé pour définir une classe.

  • La classe est une classe dans Scala. Le contenu statique ne peut pas être déclaré dans une classe. Tout le contenu statique doit être déclaré dans l'objet compagnon Object de la classe.

  • Pour les fonctions sans valeur de retour, Scala définit son type de valeur de retour comme la classe Unit.

3. Syntaxe, variables et types de données courants

1. Commentaires

Les annotations Scala sont utilisées exactement comme Java.

单行注释:// 
多行注释:/* */ 
文档注释:/** */ 

2. Variables et constantes

Constante : Une variable dont la valeur ne changera pas pendant l'exécution du programme.

  • Comparaison des variables et syntaxes constantes Java et Scala

    • Java

      • Type de variable nom de la variable = valeur initiale
      • nom de la constante de type constante finale = valeur initiale
    • Échelle

      • var nom de la variable [: type de variable] = valeur initiale

      • nom de la constante val[: type de constante] = valeur initiale

  • Fonctionnalités de déclaration de variables dans Scala

    • Lors de la déclaration d'une variable, le type peut être omis et le compilateur le déduira automatiquement, c'est-à-dire la déduction de type.

    • Une fois le type déterminé, il ne peut plus être modifié, ce qui montre que Scala est un langage de type de données puissant.

    • Lorsqu'une variable est déclarée, elle doit avoir une valeur initiale.

    • Lors de la déclaration/définition d'une variable, vous pouvez utiliser var ou val pour la modifier. Les variables modifiées par var peuvent être modifiées et les variables modifiées par val ne peuvent pas être modifiées.

    • La référence d'objet modifiée par var peut être modifiée, mais l'objet modifié par val ne peut pas être modifié, mais l'état (valeur) de l'objet peut être modifié. (Par exemple : objets personnalisés, tableaux, collections, etc.).

  • exemple de code

    • class Demo01{
              
              
      
      }
      object Demo01 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          //声明变量
          var a = 1
          var b:Int = 1
          a = 2
          b = 2
          println(a)
          println(b)
      
          //声明常量
          val c = 1
      
          //people1是var修饰的,people1的属性可以变,而且people1本身也可以变
          var people1 = new People()
          people1.name = "ls"
          people1 = null
      
          //people2是val修饰的,那么people2本身就不可变(即people2的内存地址不能变),但是people2的属性是可以变,因为属性并没有用val修饰。
          val people2 = new People()
          people2.name = "zs"
          people2 = null // 错误的,因为p2是val修饰的
        }
      }
      

3. Convention de dénomination des identifiants

La séquence de caractères utilisée par Scala pour nommer diverses variables, méthodes, fonctions, etc. est appelée un identifiant. Autrement dit : tout endroit où vous pouvez donner un nom est appelé un identifiant.

  • Règles de dénomination - la déclaration d'identifiant dans Scala est fondamentalement la même que Java, mais les détails changeront. Il existe les trois règles suivantes

    • Les identifiants Scala sont constitués de lettres, de chiffres, de traits de soulignement, de symboles mathématiques et du signe dollar, qui ne peut pas commencer par un chiffre.

    • Si l'identifiant est un symbole mathématique, alors l'identifiant doit contenir uniquement des symboles mathématiques.

    • Les identifiants de Scala peuvent être des mots-clés et des mots réservés, mais vous devez utiliser *``* pour envelopper les mots-clés et les mots réservés.

      Scala39个关键字:
      	package, import, class, object,  trait, extends, with, type, for,private, protected, abstract,  sealed, final, implicit, lazy, override try, catch, finally, throw if, else, match, case, do, while, for,  return, yield def, val, var this,super,new,true,false,null   
      
  • exemple de code

    • object Demo02 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          var a1 = 1
          var +-* = 2
          println(+-*)
          var `var` = 3
          println(`var`)
        }
      }
      

4. Sortie de chaîne

  • Le langage de sortie de Scala

    • Utilisation de l'instruction de sortie Java : System.out.xxxx

    • Syntaxe de sortie ordinaire : print println

    • Syntaxe de sortie du modèle : print/println(s"J'ai un compte : $account")

    • Syntaxe de sortie du format : printf (vous pouvez utiliser certains caractères spéciaux comme espaces réservés, puis transmettre des paramètres après la méthode pour remplacer les espaces réservés)

      • %d 十进制数字
        %s 字符串
        %c 字符
        %e 指数浮点数
        %f 浮点数
        %i 整数(十进制)
        %o 八进制
        %u 无符号十进制
        %x 十六进制
        %% 打印%
        
  • Exemple de code :

    • object Demo03 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          print("zs")
          println("ls")
          var count = "123456"
          println(s"我有一个账号:$count")
          printf("我有一个账号%s",count)
        }
      }
      

5. Saisie au clavier

En programmation, si vous avez besoin de recevoir des données d'entrée utilisateur, vous pouvez utiliser le clavier pour saisir des instructions afin de les obtenir.

Utilisez directement et de manière transparente la saisie au clavier Java——Scanner

Utilisez la saisie clavier intégrée fournie par Scala - StdIn.readxxx()

  • grammaire de base

    • StdIn.readLine()

    • StdIn.readShort()

    • StdIn.readDouble()

  • exemple de code

    • import scala.io.StdIn
      
      object Demo04 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          //字符串
          println("输入姓名:")
          var name = StdIn.readLine()
          //整形数字
          println("输入年龄:")
          var age = StdIn.readInt()
          //浮点型数字
          println("输入薪水:")
          var salary = StdIn.readDouble()
          //输出
          println(s"name = $name" )
          println(s"age = $age" )
          println(s"salary = $salary")
        }
      }
      

      image-20230911195925827

6. Type de données (points clés)

  • Java : types de données de base : quatre catégories et huit types, types de données de référence.

  • Scala : il n'existe pas de type de données de base. Tous les types sont des objets et la classe parent supérieure de tous les types est Any.

    • N'importe lequel

      • AnyVal (type numérique)

        • Octet court Int Long Flottant Double Char Booléen
        • Unit : Le remplacement parfait orienté objet pour void, Unit a une valeur unique ()
      • AnyRef (type de référence) : toutes les classes en Java, toutes les classes en Scala, toutes les collections en Scala, Null

  • Les types de données Scala adhèrent toujours à la conversion automatique (conversion implicite) des types valeur de faible précision en types valeur de haute précision.

  • StringOps dans Scala est une amélioration de String en Java.

  • Unité : correspond à void en Java, utilisé pour la position de la valeur de retour de la méthode, indiquant que la méthode n'a pas de valeur de retour. L'unité est un type de données et le seul objet est (). Void n'est pas un type de données, juste un mot-clé.

  • Null est un type et il n’existe qu’un seul objet nul. Il s’agit d’une sous-classe de tous les types référence (AnyRef) et ne peut pas être attribué Null aux types valeur.

  • Rien : c'est une sous-classe de tous les types de données. Elle est principalement utilisée lorsqu'une fonction n'a pas de valeur de retour claire, car de cette façon, nous pouvons renvoyer la valeur de retour renvoyée à n'importe quelle variable ou fonction.

  • exemple de code

    • object Demo05 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          var a:Int = 1
          var d:Byte = a.toByte//强制类型转换
          println(d)
          var b:Unit = ()
          println(b)
          var c:String = null
          var e:AnyVal = d//类似于多态
          println(e)
        }
      }
      
    • image-20230911201334210

6.1 Types entiers (Byte, Short, Int, Long)

Le type entier de Scala est utilisé pour stocker des valeurs entières, telles que 1, 2, 20, etc.

  • Classification de type entier
type de données décrire
Octet [1] Entier complémentaire à deux signé de 8 bits. La plage de valeurs est de -128 à 127
Court [2] Entier complémentaire à deux signé 16 bits. La plage de valeurs est comprise entre -32 768 et 32 767.
Int [4] Entier complémentaire à deux signé 32 bits. La plage de valeurs va de -2147483648 à 2147483647.
Longue[8] Entier complémentaire à deux signé 64 bits. La plage de valeurs va de -2 ^ 63 à 2 ^ (64-1) -1
  • Caractéristiques du type entier :

    • Chaque type entier dans Scala a une plage de représentation et une longueur de champ fixes, qui ne sont pas affectées par des opérations spécifiques pour garantir la portabilité des programmes Scala.

    • Le type entier de Scala est par défaut le type Int. Pour déclarer le type Long, ajoutez « l » ou « L » après.

    • Les variables dans les programmes Scala sont souvent déclarées comme de type Int. À moins que cela ne soit pas suffisant pour représenter de grands nombres, Long est utilisé.

6.2 Types à virgule flottante (Float, Double)

Le type à virgule flottante de Scala peut représenter un nombre décimal, tel que 1,0, 20,2f, etc.

  • Classification à virgule flottante
type de données décrire
Flotteur [4] Nombre à virgule flottante simple précision 32 bits, norme IEEE 754
Double [8] Nombre à virgule flottante double précision standard IEEE 754 64 bits
  • Caractéristiques
    • Le type à virgule flottante de Scala est par défaut le type Double. Pour déclarer le type Float, ajoutez «f» ou «F» après.

6.3 Type de caractère (Caractère)

Le type de caractère peut représenter un seul caractère et le type de caractère est Char. Les constantes de caractères sont des caractères simples entourés de guillemets simples « ».

  • Quelques caractères spéciaux dans les types de caractères

    • \t : un taquet de tabulation

    • \n : caractère de nouvelle ligne

    • \ \ :exprimer\

    • \ " :exprimer"

6.4 Type booléen (Booléen)

Le type booléen est également appelé type booléen. Les données de type booléen autorisent uniquement les valeurs vrai et faux. Le type booléen occupe 1 octet.

6.5 Type d'unité, type Null et type Nothing (souligné)

type de données décrire
Unité N'indique aucune valeur, ce qui équivaut à void dans d'autres langues. Utilisé comme type de résultat pour les méthodes qui ne renvoient aucun résultat. L'unité n'a qu'une seule valeur d'instance, écrite sous la forme ().
Nul null , le type Null n'a qu'une seule valeur d'instance null
Rien Le type Nothing se situe au niveau le plus bas de la hiérarchie des classes de Scala ; c'est un sous-type de tout autre type. Lorsqu'une fonction détermine qu'il n'y a pas de valeur de retour normale, nous pouvons utiliser Nothing pour spécifier le type de retour. Cela présente l'avantage de pouvoir attribuer la valeur renvoyée (exception) à d'autres fonctions ou variables (compatibilité).

6.6 Conversion de types

  • Conversion automatique de type numérique

Lorsqu'un programme Scala effectue une affectation ou une opération, un type de petite précision est automatiquement converti en un type numérique de grande précision. Il s'agit d'une conversion de type automatique (conversion implicite). Les types de données sont triés par taille de précision (capacité) comme :

Insérer la description de l'image ici

1. Principe d'amélioration automatique : lorsqu'il existe plusieurs types d'opérations mixtes de données, le système convertira d'abord automatiquement toutes les données dans le type de données avec une plus grande précision, puis effectuera des calculs.

2. Lors de l'attribution d'un type numérique de haute précision à un type numérique de petite précision, une erreur sera signalée, sinon une conversion de type automatique sera effectuée.

3. Il n'y a pas de conversion automatique entre (byte, short) et char.

4. Les octets, les courts et les caractères peuvent être calculés.Pendant le calcul, ils doivent d'abord être convertis en type int.

Remarque : Scala fournit également un mécanisme de conversion implicite très puissant (fonctions implicites, classes implicites, etc.)

  • casting

Le processus inverse de conversion de type automatique, convertissant un type numérique de haute précision en un type numérique de faible précision. Une fonction de conversion forcée doit être ajoutée lors de son utilisation, mais cela peut entraîner une réduction de précision ou un débordement, alors soyez prudent.

1. Pour convertir des données de haute précision en basse précision, vous devez utiliser la conversion forcée.

2. Le symbole de conversion forcée n'est efficace que pour l'opérande le plus récent et les parenthèses sont souvent utilisées pour augmenter la priorité.

  • Conversion entre le type numérique et le type String

Dans le développement de programmes, nous devons souvent convertir des types numériques de base en types String. Ou convertissez le type String en un type numérique de base.

1. Convertir le type de base en type String (syntaxe : ajouter la valeur du type de base + "")

2. Convertissez le type String en type numérique de base (syntaxe : s1.toInt, s1.toFloat, s1.toDouble, s1.toByte, s1.toLong, s1.toShort)

3. Remarque : lors de la conversion du type String en un type numérique de base, assurez-vous que le type String peut être converti en données valides. Par exemple, nous pouvons convertir "123" en un entier, mais nous ne pouvons pas convertir "hello" en un nombre entier. entier.

  • exemple de code

    • var a = "zs" + (1+1)
      

4. Opérateurs

L'utilisation des opérateurs Scala est fondamentalement la même que celle des opérateurs Java, avec seulement quelques différences.

1. Opérateurs arithmétiques

opérateur Opération exemple résultat
+ Nom positif +3 3
- négatif b = 4 ; -b -4
+ ajouter 5+5 dix
- réduire 6-4 2
* prendre 3*4 12
/ retirer 5/5 1
% Module (reste) 7%5 2
+ Ajout de chaîne "Il" + "Je pleure" "Bonjour"
  • Quant au signe de division "/", il existe une différence entre sa division entière et sa division décimale : lors de la division entre nombres entiers, seule la partie entière est conservée et la partie décimale est ignorée.

  • Modulo a%b pour un nombre, identique aux règles modulo de Java.

2. Opérateurs relationnels (opérateurs de comparaison)

opérateur Opération exemple résultat
== égal à 4==3 FAUX
!= pas égal à 4!=3 vrai
< moins que 4<3 FAUX
> plus que le 4>3 vrai
<= inférieur ou égal à 4<=3 FAUX
>= supérieur ou égal à 4>=3 vrai
  • La différence entre Java et Scala à propos de ==

    • Java:

      • ==Compare les valeurs des deux variables elles-mêmes, c'est-à-dire les premières adresses des deux objets en mémoire ;

      • equals compare si le contenu contenu dans une chaîne est le même.

    • Échelle :

      • == est plus similaire à égal en Java, qui est utilisé pour comparer les valeurs d'égalité. Utilisez la fonction eq pour comparer l'égalité de référence, c'est-à-dire l'égalité d'adresse.

3. Opérateurs logiques

La syntaxe de base est utilisée pour connecter plusieurs conditions (en général, des expressions relationnelles), et le résultat final est également une valeur booléenne.

opérateur décrire Exemple A=vrai B=faux
&& ET logique (A && B) Le résultat de l'opération est faux
|| logique ou (A || B) Le résultat de l'opération est vrai
! négation logique !(A && B) Le résultat de l'opération est vrai

4. Opérateur d'affectation

L'opérateur d'affectation attribue la valeur après une certaine opération à la variable spécifiée.

opérateur décrire Exemple
= Opérateur d'affectation simple, attribue la valeur d'une expression à la variable de gauche C = A + B affecte le résultat de l'expression A + B à C
+= Ajoutez puis attribuez la valeur C += A est égal à C = C + A
-= Soustraire puis attribuer C -= A est égal à C = C - A
*= Multiplier puis attribuer C *= A est égal à C = C * A
/= diviser puis attribuer C /= A est égal à C = C / A
%= Trouvez le reste puis attribuez la valeur C %= A est égal à C = C % A
<<= Attribuer une valeur après le décalage vers la gauche C <<= 2 à C = C << 2
>>= Attribuer après avoir décalé vers la droite C >>= 2 est égal à C = C >> 2
&= ET au niveau du bit suivi d'une affectation C &= 2 est égal à C = C & 2
^= XOR au niveau du bit puis affectation C ^= 2 est égal à C = C ^ 2
|= OU au niveau du bit suivi d'une affectation C |= 2 est égal à C = C | 2

[Note] Il n'y a pas d'opérateurs ++ et – dans Scala, vous pouvez utiliser += et -= pour obtenir le même effet ;

5. Opérateurs de bits

opérateur décrire
& opérateur ET au niveau du bit
| Opérateur OU au niveau du bit
^ Opérateur XOR au niveau du bit
~ opérateur de négation au niveau du bit
<< opérateur de décalage à gauche
>> opérateur de décalage à droite
>>> décalage à droite non signé

6. L'essence des opérateurs Scala

Un opérateur Scala est essentiellement une fonction et le nom de la fonction est un symbole mathématique

  • Lors de l'appel de méthodes sur un objet, le point peut être omis

  • Si le paramètre de fonction n'a qu'un ou aucun paramètre, () peut être omis

  • Exemple de code :

    • object Demo06 {
              
              
        def k():Unit={
              
              
      
        }
        def main(args: Array[String]): Unit = {
              
              
          val s = new String("zs")
          val s1 = "zs";
          println(s ==s1)
          println(s.eq(s1))
      
          var c: Int = 1
          c.+=(1)
          c = c+1
          println(c)
          //c++
      
          val people = new People()
          people setName "zs"
          var result = k
          println(result)
        }
      }
      

image-20230911204259832

7. Tuple

  • Type de tuple dans Scala - un type de données spécial dans Scala, classe Scala

  • Les tuples sont aussi une sorte de collection.Les collections ont une particularité : elles peuvent stocker jusqu'à 22 éléments.

  • Exemple de code :

    • object Demo07 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          val a:Tuple1[String] = new Tuple1[String]("zs")
          val b:Tuple2[String,Int] = new Tuple2[String,Int]("zs",2)
        }
      }
      

5. Contrôle des processus

  • Contrôle de flux dans Scala : contrôler la logique d'exécution du code

    • Processus séquentiel : le code est exécuté séquentiellement de haut en bas

    • Processus de branchement : emprunter différents itinéraires de branchement en fonction de différents jugements

      • if : scala et la branche if de Java sont identiques

      • switch : Scala ne fournit pas d'instruction switch, mais fournit une correspondance de modèles plus puissante pour implémenter des fonctions de type switch.

      • xxx match{

        ​ valeur de cas ou expression => {branche}

        ​ valeur de cas ou expression => {branche}

        ​ cas _ =>{}

        }

    • Processus circulaire

1. Contrôle de branche si-sinon

Pour permettre au programme de s'exécuter de manière sélective, il existe trois types de contrôle de branche : branche unique, branche double et branches multiples.

  • branche unique
    • if (条件表达式) { 执行代码块 }

Remarque : Lorsque l'expression conditionnelle est vraie, le code de { } sera exécuté.

  • double branche

    • if (条件表达式) { 执行代码块 1 } else { 执行代码块 2 }
  • plusieurs succursales

    • if (条件表达式 1) { 执行代码块 1 }else if (条件表达式 2) { 执行代码块 2 } …… else { 执行代码块 n }
  • Branches imbriquées

    • Au sein d'une structure de branche, une autre structure de branche complète est complètement imbriquée. La structure de la branche à l'intérieur est appelée la couche interne. La structure de branche à l’extérieur de la branche est appelée branche externe. Il est préférable de ne pas emboîter les branches sur plus de 3 niveaux.

    • if(){ if(){ …. }else{ …. } }

2. Changer la structure des succursales

Il n'y a pas de Switch dans Scala, mais il est géré à l'aide de la correspondance de modèles.

  • correspondance de motifs

    • 语法:  x  match{
              
              
                         case|x  [模式守卫if]  =>   case分支语句
                         case|x  [模式守卫if]  =>   case分支语句
                         case  _   =>  case分支语句
                   }
      
    • [Pattern guard] Pattern guard peut faire correspondre la plage. Généralement, lors de l'utilisation de Pattern Guard, le boîtier nécessite x

  • Exemple de code :

    • object Demo08 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          var a:String = "spring"
          a match {
              
              
            case "spring" =>
              println("春暖花开1")
              println("春暖花开2")
            case "summer" =>
              println("夏日炎炎")
            case "autumn" =>
              println("秋高气爽")
            case "winter" =>
              println("银装素裹")
            case _ =>
              println("输入的单词不是季节")
          }
      
          var b = 80
          b match {
              
              
            case b if b>=0 && b<60 =>{
              
              
              println("不及格")
            }
            case b if b>=60 && b<70 =>{
              
              
              println("及格")
            }
            case b if b>=70 && b<80 =>{
              
              
              println("中等")
            }
            case b if b>=80 && b<90 =>{
              
              
              println("良")
            }
            case b if b>=90 && b<=100 =>{
              
              
              println("优")
            }
            case _ =>
              println("输入成绩有误!")
          }
      
          var c = "zsl"
          c match {
              
              
            case "zs" => println("匹配到了张三")
            case "ls" => println("匹配到了李四")
            case _ => println("啥也没匹配到")
          }
        }
      }
      
  • Processus en boucle dans Scala : lorsqu'une certaine condition est remplie, un certain bloc de code est exécuté à plusieurs reprises.
    • java : pendant、pendant、faire pendant
    • scala : pendant, pendant, faire pendant
    • Les quatre éléments d'une boucle : variables de boucle, conditions de boucle, corps de boucle et itérations de boucle
    • Il n'y a aucune différence entre while et do while en Scala et Java, mais la boucle for est complètement différente de Java.
  • pour la boucle en Scala :
    • for (la boucle conditionnelle de type <- to/util garde l'étape de boucle ; la boucle conditionnelle de type <- to/util garde l'étape de boucle)

3. Pour le contrôle de boucle

Scala fournit de nombreuses fonctionnalités pour la structure de contrôle commune de la boucle for. Ces fonctionnalités de la boucle for sont appelées pour la dérivation ou pour l'expression.

  • boucle de données de plage vers

    • for(i <- start to end){ print(i + " ") }

      • je représente la variable de la boucle

      • <- représente la traversée de la structure grammaticale à droite

      • to signifie traverser du début à la fin, fermer à gauche et fermer à droite

  • Boucle de données de plageJusqu'à

    • for(i <- start until end) { print(i + " ") }
      • La valeur renvoie gauche fermé et droit ouvert [début, fin)
  • Boucle for améliorée – parcourir une collection ou un tableau

    • for(elem <- 集合/数组的变量)
  • garde-boucle

    • for(i <- start to end if i != num) { print(i + " ") }
      • Garde de boucle, c'est-à-dire garde de boucle (également appelé jugement conditionnel, garde). Si la garde est vraie, elle entrera dans le corps de la boucle, si elle est fausse, elle sera ignorée, de la même manière pour continuer. Équivalent àfor (i <- start to end){ if (i != num) { print(i + " ") } }
  • Taille du pas de cycle

    • for (i <- start to end by num) { println("i=" + i) }
      • by représente la taille du pas, similaire à i+=num
  • Boucles imbriquées

    • for(i <- start to end; j <- start to end) { println(" i =" + i + " j = " + j) }
      • Assurez-vous d'ajouter ; après la plage pour isoler la logique, ce qui équivaut àfor (i <- 1 to 3) { for (j <- 1 to 3) println("i ="+ i + " j=" + j) } }
  • Introduire des variables

    • for(i <- 1 to 3; j = 4 - i) { println("i=" + i + " j=" + j) }

      • Lorsqu'il y a plusieurs expressions dans une ligne de la dérivation, vous devez ajouter ; pour séparer la logique.

      • Il existe une convention non écrite pour la dérivation for : utilisez des parenthèses lorsque la dérivation for ne contient qu'une seule expression. Lorsqu'elle contient plusieurs expressions, généralement une expression par ligne, et utilisez des accolades au lieu de parenthèses, comme suit

        • for { i <- 1 to 3 j = 4 - i } { println("i=" + i + " j=" + j) }
  • valeur de retour de boucle

    • val res = for(i <- 1 to 10) yield i println(res)

      • Renvoyez les résultats traités pendant le processus de parcours dans une nouvelle collection Vector, à l'aide du mot-clé rendement.

      • Remarque : généralement rarement utilisé.

  • Imprimer dans l'ordre inverse

    • for(i <- 1 to 10 reverse){ println(i) }
      • Si vous souhaitez imprimer un ensemble de données dans l'ordre inverse, vous pouvez utiliser l'inverse.
  • exemple de code

    • object Demo09 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          /**
           * until类型的for循环
           */
          for(i <- 1 until 10){
              
              
            println(i)
          }
      
          /**
           * to类型的for循环
           */
          for(i <- 1 to 10){
              
              
            println(i)
          }
      
          /**
           * 循环守卫  等同于判断条件,循环中,满足了某个条件之后才会执行循环体
           */
          for(i <- 1 to 100 if i % 2 == 0){
              
              
            println(i)
          }
      
          /**
           * for循环的步长控制
           * 如果循环守卫和循环步长同时出现 先写循环步长 再写循环守卫
           */
            for(i <- 1 to 100 by 3 if i % 3 ==0){
              
              
              println(i)
            }
      
          /**
           * 嵌套循环
           */
            for(i <- 1 until 10;j <- 1 to i){
              
              
              print(s"$i * $j = " + (i*j) + " ");
              if (i ==j){
              
              
                println()
              }
            }
      
          /**
           * for循环的返回值 for循环不能有循环体的
           *  将for循环的结果放到一个集合当中
           */
            var a = for(i <- 1 to 10) yield i
            println(a)
      
          /**
           * for 循环的值倒序输出
           */
          import scala.language.postfixOps
            for(i <- 1 to 10 reverse){
              
              
              print(i + " ")
            }
        }
      }
      

4. boucles while et do while

L'utilisation de while et do... while en Scala est la même que celle en langage Java

  • boucle while

    • Initialisation de la variable de boucle while (condition de boucle) { itération de la variable de boucle du corps de la boucle (instruction) }
      • La condition de boucle est une expression qui renvoie une valeur booléenne
      • La boucle while consiste à juger d'abord puis à exécuter l'instruction
      • Contrairement à l'instruction for, l'instruction while ne renvoie pas de valeur, c'est-à-dire que le résultat de l'intégralité de l'instruction while est de type Unit ()
      • Parce qu'il n'y a pas de valeur de retour dans while, lorsque cette instruction est utilisée pour calculer et renvoyer des résultats, des variables sont inévitablement utilisées et les variables doivent être déclarées en dehors de la boucle while, ce qui équivaut aux effets internes de la boucle sur l'environnement externe. variables.Impact, ce n'est donc pas recommandé, mais il est recommandé d'utiliser la boucle for.
  • do while 循环控制

    • 循环变量初始化; do{ 循环体(语句) 循环变量迭代 } while(循环条件)
      • 循环条件是返回一个布尔值的表达式
      • do while 循环是先执行,再判断

5、循环终止

Scala内置控制结构特地去掉break和continue,是为了更好的适应函数式编程,推荐使用函数式的风格替代break和continue的功能而不是一个关键字。Scala中使用 breakable控制结构来实现break和 continue 功能。

6、多重循环

将一个循环放在另一个循环体内,就形成了嵌套循环。其中,for ,while ,do while 均可以作为外层循环和内层循环。

【建议一般使用两层,最多不要超过 3 层】

六、函数式编程

1、函数基础

  • 函数基本语法

    • def 函数名(参数列表):返回值类型={
              
              
         函数体
      }
      Java中的方法的定义语法:
      方法控制修饰符 [static|final|abstract] 返回值类型 方法名(参数列表) [thorws 异常]{
              
              
          方法体;
      } 
      
  • 函数和方法的区别

    • 为完成某一功能的程序语句的集合,称为函数。

    • 类中的函数称之方法。

    • Scala 语言可以在任何的语法结构中声明任何的语法。

    • 函数没有重载和重写的概念;方法可以进行重载和重写。

    • Scala 中函数可以嵌套定义。

  • 函数分类

    • 无参,无返回值
    • 无参,有返回值
    • 有参,无返回值
    • 有参,有返回值
    • 多参,无返回值
    • 多参,有返回值
class Demo10 {
    
    
 /**
  * 无参数 无返回值的函数
  */
 def a():Unit={
    
    }

 /**
  * 无参数 有返回值的函数
  */
 def b():Int={
    
    
   return 1;
 }

 /**
  * 有参数 有返回值的函数
  */
 def c(a:Int): Int = {
    
    
   return a;
 }

 /**
  * 有参数 无返回值的函数
  */
 def d(a: Int): Unit = {
    
    

 }

 /**
  * 多参数 无返回值的函数
  */
 def e(a: Int,b:Int): Unit = {
    
    

 }

 /**
  * 多参数 有返回值的函数
  */
 def f(a: Int, b: Int): Int = {
    
    
   return a+b;
 }
}

2、函数参数

  • 可变长参数

    • 如果参数列表中存在多个参数,那么可变参数一般放置在最后
  • 参数默认值,一般将有默认值的参数放置在参数列表的后面

    • 特点:如果参数带了默认值 那么传递的时候可以不用传递该参数值
  • 带名参数

    • 如果函数定义的时候 有一个参数没有默认值 而且位于参数的最后 可以使用参数名=参数值的形式传递数据
  • import java.io.IOException
    
    /**
     * 函数的第一个问题: 函数名:小驼峰
     * 函数的第二个问题: 函数的参数问题
     *     1、参数列表的声明语法:  参数名:参数类型,参数名:参数类型
     *     2、可变长形参:参数名:数据类型*  必须位于参数列表的最后一个位置,而且一个方法只能有一个可变长形参
     *     3、形参的默认值问题:scala中定义的函数参数可以带有默认值,如果一旦函数的参数带有默认值,那么调用函数时,带有默认值的参数就可以不用传递数据了
     *       一般要求默认值形参位于形参列表的最后,如果位于第一位,那么不具备默认值的形参需要通过具名实参的方式传递参数
     * 函数的第三个问题:函数的返回值问题
     *     函数的返回值可以是任何一种数据类型 Unit代表无返回值的 Nothingd
     */
    class Demo11 {
          
          
      def demo(studentName:AnyVal*):Unit={
          
          
        /**
         * 增强的for循环  <-  直接跟上一个集合
         */
        for (elem <- studentName) {
          
          
          println(elem)
        }
      }
    
      /**
       * 形参的默认值
       */
      def write(line:String,append:Boolean = true):Unit={
          
          
        println(line)
      }
    
      /**
       * 形参的默认值
       */
      def write1(append: Boolean = true,line: String): Unit = {
          
          
        println(line)
      }
    
      /**
       * 无正常返回值的函数
       */
      def test():Nothing={
          
          
        throw new IOException();
      }
    }
    object Demo11{
          
          
      def main(args: Array[String]): Unit = {
          
          
        val demo11 = new Demo11();
        demo11.demo(1,2,3)
        demo11.write("zs")
        demo11.write("zs",false)
        demo11.write1(line = "zs")
        val a = demo11.test();
      }
    }
    

3、函数的高阶函数

  • 【注】在Scala中,函数是一等公民,函数可以在Scala的任何位置充当任何的角色,函数可以声明在类中,也可以声明在函数中,还可以声明在参数列表中、还可以当作返回值,还可以当作一个变量

  • 函数当变量使用:把函数重命名了

    • var d:函数的定义 = 函数名 _

    • 【注意】函数的类型如何声明: (形参类型列表) => 返回值类型

    • 示例:
      函数的定义: def test(a:Int,b:Int):Int={
              
              a+b}
      函数的类型写法:(Int,Int) => Int
      
    • package function
      
      /**
       * 函数的高阶使用
       */
      object Demo01 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          /**
           * 1、函数充当变量使用
           * test _ 将函数整体赋值给一个变量
           */
          def test(a:Int,b:Int):Int={
              
              a+b}
          def test1(a:String,b:Int){
              
              }
      
          /**
           * 此时a是一个函数的类型
           * Scala中函数类型定义语法:(参数类型列表) => 函数的返回值类型
           */
          var a:(Int,Int) => Int = test _
          var b:(String,Int) => Unit = test1 _
      
          println(a(1,2))
          println(test(1,2))
        }
      }
      
  • 函数当参数来使用

    • 语法: def test(a:Int,f:(Int,Int)=>Int):Unit={
              
              
      
            }
      
    • package function
      
      /**
       * 函数的高阶使用:函数当作参数来使用
       */
      object Demo02 {
              
              
        /**
         * 要求 输入三个参数,其中前两个参数要根据第三个参数提供的函数计算出一个Int类型的值
         *
         * @param a
         * @param b
         * @param f
         */
        def test(a:Int,b:Int,f:(Int,Int) => Int):Unit={
              
              
          val result:Int = f(a, b)
          println(result)
        }
      
        def main(args: Array[String]): Unit = {
              
              
          /**
           * 想让test函数计算a和b的最大值
           */
          def max(a:Int,b:Int):Int={
              
              
            if (a>b)
              a
            else
              b
          }
          test(1,2,max _)//2
          test(1,2,(a:Int,b:Int)=>{
              
              a+b})//3
          test(1,2,(a,b)=>{
              
              a+b})//3
          test(1,2,(a,b)=>a+b)//3
          test(1,2,_+_)//3
      
        }
      }
      
  • 函数当作返回值来使用

    • 语法:  def test():(Int,Int)=>Int={
              
              
      
             }
      
    • package function
      
      /**
       * 函数的高阶使用--函数充当返回值
       */
      object Demo03 {
              
              
        def test(): (Int,Int)=>Int = {
              
              
           def demo(a:Int,b:Int):Int={
              
              
             a+b
           }
          return demo _
          return (a:Int,b:Int)=>{
              
              a+b}
          return (a,b)=>{
              
              a+b}
          return (a,b)=>a+b
          return _+_
        }
      
      }
      
def test(a:Int,b:Int):Int = {
    
    
   a+b
}
var f1:(Int,Int)=>Int = test _
var f2:(Int,Int)=>Int = (a:Int,b:Int) => {
    
    a+b} //使用匿名函数
var f3:(Int,Int)=>Int = _ + _

4、函数的高阶使用

  • 函数的闭包问题

    • 函数闭包指的是将不属于本函数的变量或者对象也包含进来,直到该函数运行完成,外部变量或者对象才可以被释放。

    • package function
      
      object Demo04 {
              
              
        def main(args: Array[String]): Unit = {
              
              
           var x:Int = 1
           def test(a:Int):Int={
              
              
             a*x
           }
          test(1)
        }
      }
      
  • 函数的柯里化

    • 将一个接收多个参数的函数给他转换成为一个接收单个参数的函数的过程

    • 将一个接收多个参数的函数转换成为一个返回了函数的函数,返回的函数传递的值就是原先的第二个参数

    • 其实是闭包的一个使用场景

    • package function
      
      /**
       * 函数的柯里化
       *   test(1,2)
       *   test(1)(2)
       */
      object Demo05 {
              
              
        def sum(a:Int,b:Int,c:Int):Int={
              
              
          a+b+c
        }
      
        def sum1(a:Int):Int=>Int=>Int={
              
              
          def sum2(b:Int):Int=>Int={
              
              
            def sum3(c:Int):Int={
              
              
              a+b+c
            }
            return sum3 _
          }
          return sum2 _
        }
      
      
        def test(a:Int,b:Int=1):Int={
              
              
          a*b
        }
      
        /**
         * test1函数返回的是一个函数 函数的类型是Int=>Int
         * 返回的函数的输入参数是原先函数的第二个参数
         * 返回的函数的输出是原先函数的计算结果类型
         * @param a
         * @return
         */
        def test1(a:Int):Int=>Int={
              
              
          (b:Int)=>{
              
              a*b}
        }
      
        def main(args: Array[String]): Unit = {
              
              
          var r:Int = test(1,2)
          println(r)
      
          var r1:Int = test1(1)(2)
          println(r1)
      
          sum(1,2,3)
          var r2:Int = sum1(1)(2)(3)
          println(r2)
        }
      }
      
      案例:   
      def test1(a:Int,b:Int,c:Int,d:Int):Int={
              
              
        a+b+c+d
      }
      
      def sum1(a:Int):Int =>Int =>Int => Int = {
              
              
        def sum2(b:Int):Int =>Int => Int = {
              
              
          def sum3(c:Int):Int =>Int = {
              
              
            def sum4(d:Int):Int = {
              
              
              a+b+c+d
            }
            sum4 _
          }
          sum3 _
        }
        sum2 _
      }
      var sum:Int = sum1(1)(2)(3)(4)
      var sumT:Int = test1(1,2,3,4)
      println(sum + " " + sumT)/
      
  • 递归函数

    • 函数内部调用本函数

    • 递归三要素

      • 1、递归入口:自己调用自己的的逻辑
      • 2、递归出口:不能调用自己的逻辑
      • 3、递归条件必须向出口迭代
    • package function
      
      object Demo06 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          /**
           * 定义一个函数 求∑100
           */
          var r = sum(1000000)
          println(r)
        }
      
        def sum(a:Int):Int={
              
              
          if(a == 1){
              
              
            1
          }else{
              
              
            a+sum(a-1)
          }
        }
      }
      
  • 函数调用的惰性加载

    • 惰性加载指的是将函数的调用延迟到第一次使用函数的返回值的时候才会调用

    • 使用语法: lazy val 变量名 = 函数名(实参)
      此时函数的调用在第一次使用变量的时候才会调用
      一旦惰性加载,变量名只能使用val修饰

    • package function
      
      object Demo07 {
              
              
        def sum(a:Int,b:Int):Int = {
              
              
          println("sum函数执行了")
          a+b
        }
      
        def main(args: Array[String]): Unit = {
              
              
          //函数的调用被惰性加载了
          lazy val a = sum(1,2)
          println("main函数中sum函数调用之后的输出")
          println(a)
        }
      }
      

5、函数的简化操作

  • 声明的简化

    • 1、如果函数没有参数,那么函数的括号可以省略
      def test:Unit={}
    • 2、函数的返回值可以省略的,可以根据函数体的最后一行自动推断,【注意】如果函数体的最后一行使用return 关键字返回数据,那么函数的返回值一定不能省略的
      def test = {
      1
      }
    • 2、函数的返回值可以省略的,可以根据函数体的最后一行自动推断,【注意】如果函数体的最后一行使用return 关键字返回数据,那么函数的返回值一定不能省略的
      def test = {
      1
      }
    • 3、函数体中,函数的返回值前的return关键字可以省略的,自动根据最后一行推断函数的返回值
    • 4、如果函数的返回值类型是Unit类型 那么=号和函数的返回值都可以省略
      def test{}
    • 5、匿名函数
      • 定义:定义函数时,只关注函数的逻辑,不关注函数的名字,此时我们就可以使用匿名函数来定义函数:
        (形参列表) => {函数体}
      • 使用场景:当函数当作参数或者当作返回值使用的时候,可以使用匿名函数传递
      • 简化
        • 1、匿名函数的形参列表的类型可以省略的,因为当作参数或者返回值使用的时候,参数的类型定义死了
        • 2、如果匿名函数的函数体只有一个,那么{}可以省略了
        • 3、如果形参的参数名在函数体中只出现了一次,那么参数名就可以使用_替代,同时形参列表可以省略了
  • 调用的简化:一般不建议使用,建议运算符的函数调用简化

    • 调用的语法:对象名|类名.函数名(实参列表)
    • 1、调用的点.可以省略的,对象名|类名 函数名(实参列表)
    • 2、如果实参列表为空,那么()可以省略,如果声明函数的时候没有加() 那么调用的时候一定不能加()
    • 3、如果函数的实参列表只有一个 那么()也可以省略
      对象名|类名 函数名 唯一的实参
  • /**
     * 函数的简化操作:
     *   Scala信奉一个原则:至简原则
     *   函数基于这个原则,我们就可以进行相应的简化:简化可以从声明和调用两个层面简化
     * 声明的简化规则:
     *   1、如果函数的参数没有 那么()可以省略
     *   2、函数的返回值不用加,可以根据函数的最后一行自动推断,最后一行返回的数据return关键字可以省略的 如果return没有省略 那么返回值类型一定要写上的
     *   3、如果函数的返回值是unit类型的,那么返回值类型和=号都可以省略
     *   4、如果函数的函数体只有一行 那么{}可以省略
     *   5、如果函数名没有意义,那么函数名可以省略的(函数充当参数或者返回值使用的--高阶函数用法)
     *
     * 调用的简化规则:
     *   1、如果函数没有参数,那么调用的时候 括号可以加也可以不加,但是如果函数声明的时候没有加括号 那么调用的时候一定不能加括号
     *   2、调用函数的时候 点可以省略的 如果参数只有一个 调用的时候()可以省略
     */
    object Demo12 {
          
          
      def main(args: Array[String]): Unit = {
          
          
        test
        Demo12 test4 1;
      }
    
      /**
       * 没有参数可以不用加括号
       */
      def test:Unit={
          
          }
    
      def test1(a:Int,b:Int):Int={
          
          
        return a+b
      }
    
      def test2{
          
          }
    
      def test3(a:Int,b:Int)=a+b
      def test4(a:Int){
          
          }
    }
    

七、面向对象

Scala源于Java中,因此在Scala中也存在面向对象编程思想,面向对象编程最核心的逻辑就是以类来组织代码,以对象来调用代码。Scala的面向对象和Java基本上思维是一致的,只不过就是语法稍微不一样而已。

1、包和import导入

  • 包package:包是用来分类管理Scala代码的,将不同类型的代码放到不同的包下,便于我们管理

  • Scala包有两种管理代码的方式

    • 采用和Java一样的管理机制,新建包,包下可以新建类和子包

    • 采用包对象的管理机制,实现一个文件中存在多个包和多个scala类

      • package com{
                  
                  
          package nuckl{
                  
                  
            class B{
                  
                  
        
            }
          }
          class A{
                  
                  
        
          }
        }
        
  • Scala中类的导入问题import

    • 在当前Scala类中,如果要使用非本包下的代码,那么我们就得需要通过import关键字导入才能使用。

    • 每一个Scala类默认导入三个包

      • java.lang._
      • scala._
      • scala.Predef._
    • Scala类中导入有一些规则和Java有点不一样

      • 1、Scala可以在任何位置进行导包操作,代码只能在导包位置之后使用
        我们可以把所有的包放到package之后 class之前
      • 2、如果我们要导入一个包下的所有代码,那么可以使用_当作通配符使用
      • 3、我们现在只想导入某一个包下的两个类,而非所有类
        import xxxx.{x1,x2}
      • 4、导包重命名操作:可以将一个类重命名为另外一个名字在当前类中使用
        import xxxx.{x1=>x2} x1类在当前类中可以使用x2名字来替代
      • 5、屏蔽某一个包下的部分类:导入一个包下的所有代码,除了某几个类之外
        import xxxx{x1=>_,x2}
        导入xxxx包下的x2类,不导入x1这个类
    • package importstudy
      
      import java.util.{
              
              Date, Scanner}
      import java.sql.{
              
              Date => SQLDate}
      
      /**
       * 导包的规则
       */
      class Demo01 {
              
              
        def test():Unit = {
              
              
          var sc = new Scanner(System.in);
          var d = new Date()
          var f = new SQLDate(1)
        }
      }
      

2、面向对象中的类

  • 类的定义

    • 访问控制修饰符 class className 访问控制修饰符(主构造器参数列表){
              
              
          类体
      }
      
    • 访问控制符:三个 private protected public(不写)

  • 在同一个Scala文件中可以存在多个Scala类,权限没要求的

3、面向对象中类的属性

属性用来描述类的特征

声明语法:访问控制修饰符 var|val 属性名:属性类型 = 值;
属性声明的时候必须加值,但是我不想给其他值,只想给默认值,那么值使用_ 来代替

【注意】val修饰的属性 不能赋予_ 默认值,必须给一个显示的值

package classstudy

import scala.beans.BeanProperty

class Demo01 {
    
    
  @BeanProperty var name:String = _
  @BeanProperty val age:Int = 1
}
class Demo02{
    
    

}
object Demo02{
    
    
  def main(args: Array[String]): Unit = {
    
    
    var a:Demo01 = new Demo01()
    var b:Demo02 = new Demo02()

    println(a.getName)
    a.setName("kkkk")
    println(a.getName)
    println(a.getAge)
    println(a)
  }
}

image-20230912172443328

属性前加一个注解@BeanProperty

4、面向对象中类的方法

  • 方法就是函数,函数声明在类中,函数称之为方法

  • 语法:  
    访问控制修饰符   def  方法名(形参列表):方法的返回值类型 ={
          
          
       方法体
    }
    

5、面向对象中类的代码块和内部类

{} 类中类

6、面向对象中类的构造器

  • 构造器是创建该类的实例对象的

  • Scala有两种构造器

    • 1、主构造器:声明在类上的 class ClassName 访问控制修饰符 (形参列表)–主构造器

    • 2、辅助构造器:声明在类中的构造器,

      • 语法:
        def   this(形参列表){
                  
                  
        
        }
        
    • 辅助构造器必须在首行直接或者间接的调用主构造器代码

  • 【注意】

    • 主构造器不存在构造体,那么也就意味着主构造器无法给属性赋值,为了可以给属性赋值,主构造器的形参列表有个变化,主构造器的形参列表可以使用var或者val修饰,一旦主构造器的形参使用var val修饰 那么主构造器中的形参就是类的属性了

    • 主构造器我们一般都是要求是无参构造器,而且主构造器一旦是无参的,那么主构造器的()可以省去

    • package constructor
      
      class People private ( var name:String,var age:Int){
              
              
          def this(name:String){
              
              
            this(name,1)
          }
      }
      class Student private{
              
              
      
      }
      object People {
              
              
        def main(args: Array[String]): Unit = {
              
              
          val people = new People("zs",21)
          println(people.name)
          println(people.age)
          //val people1 = new People("zs")
        }
      }
      

7、Scala中对象的创建

对象的创建就是变量|常量的定义

var|val 对象名:类 = new 类名(实参)

简化:类型可以省略,自动推断;如果调用的构造器的实参为空,那么()也可以省略的。

8、面向对象的特征

  • 封装性

    • 和Java的封装一样的概念,合理隐藏、合理暴露,控制类、属性、方法、构造器、内部类能被谁访问使用,不能被谁访问使用。

    • Scala的封装权限只有三种:private protected 不写(public)

    • 封装性和Java的区别在于两个地方

      • protected的权限比Java的权限更加严格:只有当前类和子类能访问,同包下的类都无法访问。
      • private的权限是私有化的,但是Scala开后门,private[包名] 只有当前类和指定包下能访问了,包一般是一个根包。
    • package encapsulation.demo
      
      class Demo01 private[encapsulation]{
              
              
          
      }
      ====================================================
      package encapsulation.demo01
      
      import encapsulation.demo.Demo01
      
      object Demo02 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          val d = new Demo01()
          println(d)
        }
      }
      
  • 继承性

    • 和Java的概念是一样的,extends继承,Scala也是单继承,一旦继承父类,拥有父类中非私有化的属性和方法。

    • package inheritance
      
      class Father {
              
              
        private var name:String = _
        protected var age:Int = _
        var sex:String = _
      
        private def test1(): Unit = {
              
              
      
        }
        protected def test2(): Unit = {
              
              
      
        }
        def test3(): Unit = {
              
              
      
        }
      
      }
      
      class Son extends Father{
              
              
      
      }
      
      object Son{
              
              
        def main(args: Array[String]): Unit = {
              
              
          var son = new Son();
          println(son.age)
          println(son.sex)
          son.test2()
          son.test3()
        }
      }
      
  • 多态性

    • 定义变量的时候,分为编译时类型和运行时类型

    • 向上转型:将儿子的对象给了父类的变量引用,可以直接给,不需要任何多余的操作。
      var s:Father = new Son()

    • 向下转型:将父亲给儿子,不能直接给,需要使用asInstanceof[子类] 赋值,要求父亲的运行时类型必须是儿子或者儿子的子类类型。
      var s:Father = new Son()
      var s1:Son = s.asInstanceof[Son]

    • 如果我们要进行向下转型,最好先使用Scala提供的以下代码先判断父类的运行时类型是不是子类的类型。
      对象名.isInstanceof[ClassName]

    • classof[类名] 获取一个类的运行时类 返回的是一个Class类的对象

    • object Son{
              
              
        def main(args: Array[String]): Unit = {
              
              
          /**
           * 向上转型可以直接转换
           */
          var son:Father = new Son()
          son.test3()
          /**
           * 向下转型 需要强转 asInstanceof[Son]
           */
          var son1:Son = son.asInstanceOf[Son]
          println(son1)
          var son2:Father = new Father()
          if(son2.isInstanceOf[Son]){
              
              
            var son3: Son = son2.asInstanceOf[Son]
            println(son3)
          }else{
              
              
            println("son2不是Son的类型,无法向下转型")
          }
        }
      }
      
      
      package review
      
      class Demo02{
              
              
      
      }
      
      object Demo02 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          var a = new Demo02
          val clazz = a.getClass
          println(clazz)//class review.Demo02
          val value: Class[Demo02] = classOf[Demo02]
          println(value)//class review.Demo02
        }
      }
      
  • 抽象性

    • 抽象类

      • abstract class ClassName{
                  
                  
            抽象属性 抽象方法
        }
        
    • 抽象属性

      • 没有 = 赋值的属性就是抽象属性
    • 抽象方法

      • 没有函数体的方法称为抽象方法
    • Scala中非抽象子类重写抽象类的属性和方法时,为了表示重写的概念,加了override关键字表示重写的过程

    package abstractstudy
    
    abstract class Animal (){
          
          
      //抽象属性  抽象属性也是要被非抽象子类重写的
      var name:String
      var age:Int = 1
      //抽象方法 就是没有函数体的方法
      def test():Unit
      def test1():Unit={
          
          
    
      }
    }
    
    class Dog extends Animal{
          
          
      override var name: String = _
    
      override def test(): Unit = {
          
          
    
      }
    }
    object Dog{
          
          
      def main(args: Array[String]): Unit = {
          
          
        val dog = new Dog
        dog.test()
        println(dog.name)
    //    val animal = new Animal();
      }
    }
    
  • Scala中伴生对象Object

    • Object定义的属性和方法就是当前Class类的静态内容,静态内容可以直接使用类名来调用

    • Object类中存在一个功能特别强大的方法,apply方法

      • apply方法可以让我们创建对象的时候不需要使用new关键字,而是直接使用类名(形参列表)的形式构建类的对象。

      • def apply(形参列表):Class ={
                  
                  
             new  ClassName(实参);
        }
        
    • package objectstudy
      
      import objectstudy.Demo01.age
      
      class Demo01 {
              
              
        def this(name:String){
              
              
          this()
          this.name = name
        }
        var name:String = _
        def test():Unit = {
              
              
          println(age)
          test()
        }
      }
      object Demo01{
              
              
        def main(args: Array[String]): Unit = {
              
              
          var d = Demo01()
          var d1 = Demo01("kl")
          println(d1)
          println(d1.name)
        }
        var age:Int = _
        def test01():Unit={
              
              
          //println(name)
        }
        def apply():Demo01 = {
              
              
          new Demo01
        }
        def apply(name:String):Demo01={
              
              
          new Demo01(name)
        }
      }
      
  • Scala中的case class样例类

    • 样例类就等同于Java中JavaBean,同时Scala提供case class是为了丰富模式匹配的功能的。

    • 样例类的语法

      • case class(形参列表) extends Father with T1
      • 形参列表既是类的属性 还是类的主构造器,而且形参列表默认是使用private val修饰符的 ,同时样例类自动给我们生成类的toString、hashCode、equals、apply方法。
      • 和模式匹配结合使用的。
    • package objectstudy
      
      import scala.beans.BeanProperty
      
      object Demo02 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          var p:People = new People("zs",20)
          var p1:People = People("zs",20)
          println(p)//People(zs,30)
          println(p1)//People(ls,20)
          println(p == p1)//true
          println(p.getName)//zs
          println(p.setName("kl"))//()
          println(p.getName)//kl
      
        }
      }
      
      case class People(@BeanProperty var name:String, age:Int){
              
              
      
      }
      
    • package caseclass
      
      abstract class Traffic{
              
              
      
      }
      case class Car(pinpai:String,pailiang:Double) extends Traffic
      case class Plane(rongliang:Int) extends Traffic
      
      /**
       * 样例类和模式匹配的结合使用
       */
      object Demo{
              
              
        def judgeTraffic(traffic: Traffic):Unit = {
              
              
            traffic match {
              
              
              case Car(a,b) if b>1.2 => println(s"这是一个小汽车给,品牌是$a,排量是$b")
              case Plane(c) => println(s"这是一个飞机,容量是$c")
              case _ => println("这个交通工具不识别")
            }
        }
      
        def main(args: Array[String]): Unit = {
              
              
          var traffic:Traffic = Car("问界M7",1.0)
          var traffic1:Traffic = Plane(6)
          judgeTraffic(traffic)
          judgeTraffic(traffic1)
        }
      }
      
  • Scala中的特质Trait

    • 特质就是Java中的接口,只不过在Java中称之为接口,在Scala中称之为特质。Java中的所有接口都可以当作Scala的特质使用。

    • 创建语法

      • trait  特质名{
                  
                  
            抽象属性 抽象方法 普通的属性 普通的方法
        }
        
    • 使用

      • Scala中特质也是需要继承的,父类也是继承的
        class Son extends Father with Trait1 with trait2
package traitstudy
  
trait FlyAble {
    
    
  //抽象属性
  var name:String
  //抽象方法
  def fly():Unit
  //普通的属性
  var age:Int = _
  //普通方法
  def test():Unit ={
    
    
  
  }
}
class Animal{
    
    }
class Bird extends Animal with FlyAble with Comparable[Bird]{
    
    
  override var name: String = _
  
  override def fly(): Unit = {
    
    
  
  }
  
  override def compareTo(o: Bird): Int = {
    
    
    return 1
  }
}

八、集合

Scala中可以使用Java的集合,但是Scala也给我们提供了一套集合体系,Spark Kafka既支持Scala集合体系,还支持Java集合体系。

1、Java集合体系

  • Collection:单列集合(一行数据只有一列)
    • List:元素可重复、且元素加入有序、可以根据索引取值
      • Vector
      • ArrayList
      • LinkedList
    • Set:元素不可重复、没有索引的概念
      • HashSet:元素无序
      • LinkedHashSet:元素加入有序
      • TreeSet:元素是大小有序,需要用到比较器
  • Map:双列集合,key值不可重复,value可重复
    • HashMap
    • HashTable
      • Properties
    • LinkedHashMap
    • TreeMap

2、Scala集合体系

  • 不可变集合体系:每一次操作集合都是返回一个新的集合对象,而原有的集合不受任何的影响
    包:scala.collection.immutable

    • Set:不可重复

    • Map:双列

    • Seq:可以重复

    • Set、Map 是 Java 中也有的集合 ;Seq 是 Java 没有的,我们发现 List 归属到 Seq 了,因此这里的 List 就和 Java 不是同一个概念了

      IndexedSeq 和 LinearSeq 的区别:

      (1)IndexedSeq是通过索引来查找和定位,因此速度快,比如 String 就是一个索引集合,通过索引即可定位

      (2)LinearSeq 是线型的,即有头尾的概念,这种数据结构一般是通过遍历来查找

  • 可变集合体系:每一次操作集合都是对原有的集合对象进行操作,而不是返回新的集合对象
    包:scala.collection.mutable

    • Set
    • Map
    • Seq

3、Scala集合的使用

  • Scala中数组-Seq的使用

    • 不可变数组:Array

    • 可变数组:ArrayBuffer

    • package collection
      
      import scala.collection.mutable.ArrayBuffer
      
      /**
       * 数组的定义和使用
       */
      object ArrayStudy {
              
              
        def main(args: Array[String]): Unit = {
              
              
          /**
           * 1、不可变数组的创建
           * (1)new 创建
           * (2)Array提供的伴生对象的apply方法来创建
           */
            var array:Array[Int] = new Array[Int](10)
            array(0) = 1
            println(array(0))//1
            var array1 = Array(1,2,3,4,5,6,7,8,9,10)
            println(array1(1))//2
      
          /**
           * 2、可变数组 ArrayBuffer
           */
          var ab:ArrayBuffer[Any] = ArrayBuffer[Any]()
          ab.append(1)
          ab.append(2)
          ab.append(3)
          println(ab)//ArrayBuffer(1, 2, 3)
      
          /**
           * 3、可变数组与不可变数组的互相转换
           */
          array1.toBuffer //不可变数组转可变数组
          ab.toArray //可变数组转不可变数组
      
          /**
           * 4、多维数组
           */
          val array2:Array[Array[Int]] = Array.ofDim(2, 3)
          println(array2(0)(1))//0
          //数组的遍历
          for(elem:Array[Int] <- array2;a <- elem){
              
              
      
          }
          for(i <- 0 to array2.length-1){
              
              
      
          }
        }
      }
      
  • Scala中List列表的使用

    • 不可变列表:List

    • 可变列表:ListBuffer

    • package collection
      
      import scala.collection.mutable.ListBuffer
      
      object ListStudy {
              
              
        def main(args: Array[String]): Unit = {
              
              
          /**
           * 1、不可变列表
           * List的伴生对象的apply方法构建的
           */
          var list:List[Int] = List[Int](1,2,3)
          //:: list集合的一种特殊运算符  代表在集合的头部添加一个新的元素 而且会给我们返回一个新的集合
          //:: 可以添加多个元素
          list = 4 :: 5 :: 6 :: list//List(4, 5, 6, 1, 2, 3,)
          //如果添加单个元素 使用 +:  :+
          list = list :+ 7//尾部添加
          list = 8 +: list//头部添加  //List(8, 4, 5, 6, 1, 2, 3, 7)
      
          var list1:List[Int] = List[Int](10,11)
          //:::(扁平化操作)  将左边的集合中元素一个一个加到右边的集合中  而不是将左边的集合当作一个整体添加
          list = list1 ::: list//List(10, 11, 8, 4, 5, 6, 1, 2, 3, 7)
          println(list)//List(8, 4, 5, 6, 1, 2, 3, 7)
      
          var list2 = 4 :: 5 ::List(1,2,3) :: Nil//List(4, 5, List(1, 2, 3))
          var list3 = 4 :: 5 ::List(1,2,3) ::: Nil//List(4, 5, 1, 2, 3)
          println(list3)
      
          //移除左边的多少个元素
          list3 = list3.drop(3)//List(2, 3)
          list3 = list3.updated(0,22)//List(22, 3)
          println(list3)
          println(list3(0))//22
          //遍历数组
          list3.foreach((a:Int)=>{
              
              println(a)})//22   3
      
          /**
           * 可变ListBuffer
           */
          var lb = ListBuffer[Int](1,2,3,4)
          //添加数据
          lb.append(5)//默认添加到末尾
          lb.insert(1,6)//默认添加到开头
          lb.+=(7)//默认添加到末尾
          println(lb)//ListBuffer(1, 6, 2, 3, 4, 5, 7)
          //移除数据
          lb.remove(1)//移除目标索引的数据
          lb.-=(1)//移除目标值 lb -= 1
          println(lb)//ListBuffer(2, 3, 4, 5, 7)
          //取值
          println(lb(1))//3
          //遍历元素  1、索引遍历 2、增强的for循环  3、foreach
          lb.foreach(println)// 2 3 4 5 7
          //修改数据
          lb.update(1, 56)
          println(lb)//ListBuffer(2, 56, 4, 5, 7)
        }
      }         
      
  • Scala中Set集合的使用

    • 不可变Set集合:Set

    • 可变Set集合:Set

    • package collection
      
      object SetStudy {
              
              
        def main(args: Array[String]): Unit = {
              
              
          /**
           * 不可变的Set集合
           */
          //1、创建不可变Set集合
          var set:Set[Int] = Set[Int](1,2,3,4,5,1,2)//HashSet(5, 1, 2, 3, 4)
          //2、set集合中添加数据
          set = set + 6
          //3、set集合删除数据
          set = set - 1//HashSet(5, 6, 2, 3, 4) 减的是元素
          println(set)
      
          /**
           * 可变的set集合
           */
          var set1 = scala.collection.mutable.Set[Int](1,2,3,4,5,6,5,6)
          //1、添加数据
          set1.add(88)//HashSet(1, 2, 3, 4, 5, 6, 88)
          set1 += 99//HashSet(1, 2, 3, 99, 4, 5, 6, 88)
          //2、删除数据
          set1.remove(88)//HashSet(1, 2, 3, 99, 4, 5, 6)
          set1 -= 3//HashSet(1, 2, 99, 4, 5, 6)
          println(set1)
        }
      }
      
  • Scala中元组Tuple

    • package collection
      
      object TupleStudy {
              
              
        def main(args: Array[String]): Unit = {
              
              
          /**
           * 元组是Scala中一种比较特殊的“集合”类型 元组也可以存放一组数据,但是这一组数据类型可以不一致
           * 元组的存放的数据个数是有限制的,最小1个 最多22个
           * 因此元组在Scala中有一个专业的叫法:一元组 .... 二十二元组
           * Tuple1
           * Tuple2
           * ...
           * Tuple22
           */
          //元组的创建有三种方式:
          var t1:Tuple2[String,Int] = new Tuple2[String,Int]("zs",20)
          var t2:Tuple2[String,Int] = ("ww",20)
          var t3:Tuple2[String,Int] = Tuple2[String,Int]("ls",20)
          println(t1)//(zs,20)
          println(t2)//(ww,20)
          println(t3)//(ls,20)
          var t4:Tuple3[Int,Int,Int] = (1,2,3)
          println(t4)//(1,2,3)
          //元组的类型有两种声明方式:TupleN[xxx,xxx]   (xxx,xxx)
          var t5:(String,Int) = new Tuple2[String,Int]("kl",20)
          println(t5)//(kl,20)
      
          /**
           * 获取元组中元素
           * 元组提供了一个属性  _x
           * 在Scala当中map集合的kv可以当作二元组来处理(添加数据,foreach)
           */
          println(t4._3)//3
          println(t5._1)//kl
          println(t5._2)//20
        }
      }
      
  • Scala中Map集合的使用

    • package collection
      
      object MapStudy {
              
              
        def main(args: Array[String]): Unit = {
              
              
          /**
           * 1、不可变的Map集合
           */
          var map:Map[String,Int] = Map[String,Int]("zs"->20,"ls"->30,"kl"->20,"zs"->40)
          println(map)//Map(zs -> 40, ls -> 30, kl -> 20)
          //添加数据  添加数据 需要传入一个二元组 Tuple2
          map = map + (("hyf",18))//Map(zs -> 40, ls -> 30, kl -> 20, hyf -> 18)
          //删除数据
          map = map.-("ls")//Map(zs -> 40, kl -> 20, hyf -> 18)
          //更新数据
          map = map.updated("kl",23)//Map(zs -> 40, kl -> 23, hyf -> 18)
          // 获取key对应的value
          val value1:Int = map.getOrElse("hyf", 10)//18
          val value2:Int = map.getOrElse("ww", 999)//999
          println(value2)
          println(map)
          //遍历
          for(elem <- map.keys){
              
              
            println(map.get(elem).get)//40 23 18
          }
          map.foreach((tuple:(String,Int)) => {
              
              println(s"key=${
                
                tuple._1} value=${
                
                tuple._2}")})
          //key=zs value=40
          //key=kl value=23
          //key=hyf value=18
      
          /**
           * 2、可变的Map集合
           */
          val map1 = scala.collection.mutable.Map("a" -> 1, "b" -> 2, "c" -> 3)
          println(map1)//HashMap(a -> 1, b -> 2, c -> 3)
          //向集合增加数据
          map1 += ("d" -> 4)
          println(map1)//HashMap(a -> 1, b -> 2, c -> 3, d -> 4)
          // 将数值4添加到集合,并把集合中原值1返回
          val maybeInt: Option[Int] = map1.put("a", 4)
          println (maybeInt.getOrElse(0))//1
          println(map1)//HashMap(a -> 4, b -> 2, c -> 3, d -> 4)
          map1 += ("b" -> 44) // 这里会将键 "b" 的值更新为 44 或者添加一个新的键值对
          println(map1)//HashMap(a -> 4, b -> 44, c -> 3, d -> 4)
          //删除数据
          map1.-=("b", "c")
          println(map1)//HashMap(a -> 4, d -> 4)
          //修改数据
          map1.update("d", 5)
          println(map1)//HashMap(a -> 4, d -> 5)
          map1("d") = 66
          println(map1)//HashMap(a -> 4, d -> 66)
          //打印集合
          map1.foreach((kv) => {
              
              
            println(kv)
            //(a,4)
            //(d,66)
          })
        }
      }
      

4、Scala中集合的一些常用函数

  • 基本函数

    • xxx.length —— 获取集合长度

    • xxx.size —— 获取集合大小

    • xxx.foreach(函数) —— 循环遍历

    • xxx.mkString(“分隔符”) —— 生成字符串

    • xxx.contains(xxxx) —— 是否包含

    • xxx.iterator ——迭代器

    • package collection
      
      import scala.collection.mutable.ListBuffer
      
      object Demo01 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          /**
           * 测试集合的常用基本函数
           */
          var list1 = List[Int](1,2,3,4,5)
          println("-------不可变List-------")
          println(list1.length)
          println(list1.size)
          list1.foreach((a:Int)=>println(a))
          list1.foreach(println)//简化形式
          println(list1.mkString("=="))
          println(list1.contains(1))
          var list2 = ListBuffer[Int](1,2,3,4,5)
          println("-------可变List-------")
          println(list2.length)
          println(list2.size)
          list2.foreach((a: Int) => println(a))
          list2.foreach(println) //简化形式
          println(list2.mkString("=="))
          println(list2.contains(1))
      
          var map = Map[String, Int]("zs" -> 20, "ls" -> 20)
          println("-------可变Map-------")
          println(map.size)
          map.foreach(println)
          println(map.mkString("=="))
          println(map.contains("zs"))
        }
      }
      
    • image-20230917095509701

    • image-20230917095520378

  • 集合的一些高级函数

    • 获取集合的头 head()

    • 获取集合的尾(不是头的就是尾) tail

    • 集合最后一个数据

    • 集合初始数据(不包含最后一个)

    • 反转

    • 取前(后)n 个元素

    • 去掉前(后)n 个元素

    • 并集

    • 交集

    • 差集

    • fermeture éclair

    • fenêtre coulissante

    • package collection
      
      /**
       * 集合的高级函数
       */
      object Demo02 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          var list = List[Int](1,2,3,4)
          println(list.head)
          println(list.tail)
          println(list.last)
          println(list.init)
          println(list.reverse)
          println(list.take(2))
          println(list.takeRight(3))
          println(list.drop(1))
          println(list.dropRight(1))
      
          var list1 = List[Int](4,5,6,7,8,9)
          println(list.union(list1))
          println(list.concat(list1))
          println(list.intersect(list1))
          println(list.diff(list1))
          println(list1.diff(list))
          var col:List[(Int,Int)] = list.zip(list1)
          println(col)
      
          /**
           * 滑窗
           */
          var list2 = List[Int](1,2,3,4,5,6,7,8,9,10,11,12,13)
          var list3:Iterator[List[Int]] = list2.sliding(3,1)
          while(list3.hasNext){
              
              
            println(list3.next())
          }
        }
      }
      
    • image-20230917102227588

  • Définir la fonction de calcul

    • somme

    • Trouver le produit

    • valeur maximum

    • valeur minimum

    • trier

      • sorted(implicit ord: Ordering[B]) : comparez la taille des éléments de la collection actuelle, puis triez. Le principe est que les éléments de la collection doivent être de taille comparable. Si la taille ne peut pas être comparée, alors un comparateur doit être passé. Renvoie une valeur de type int

      • sortedBy(f: xx=>xxx)((implicit ord: Ordering[xxx])) : Convertissez les éléments de la collection en un autre type, puis comparez en fonction du type converti

      • sortWith(f:(xx,xx)=>Boolean) : Personnalisez les règles de comparaison des éléments et renvoyez une valeur de type booléen

      • package collection
        
        class People(var name: String ,var age: Int ){
                  
                  
          override def toString: String = s"People{name=$name,age=$age}"
        }
        object People{
                  
                  
          def main(args: Array[String]): Unit = {
                  
                  
            var p1 = new People("zs",20)
            var p2 = new People("ls",30)
            var p3 = new People("ww",18)
            var list:List[People] = List[People](p1,p2,p3)
            println(list)
            var list1 = list.sorted(new Ordering[People] {
                  
                  
              override def compare(x: People, y: People): Int = {
                  
                  
                if (x.age > y.age){
                  
                  
                  1
                }else{
                  
                  
                  -1
                }
              }
            })
            println(list1)
            var list2 = list.sorted((x:People,y:People)=>{
                  
                  
              if (x.age>y.age){
                  
                  
                1
              }else{
                  
                  
                -1
              }
            })
            println(list2)
            var list3 = list.sorted((x:People,y:People)=>x.age-y.age)
            println(list3)
        
            val list4 = list.sortBy((x: People) => x.age)
            println(list4)
        
            var list5 = list.sortWith((x:People,y:People)=>{
                  
                  
              if (x.age>y.age){
                  
                  
                true
              }else{
                  
                  
                false
              }
            })
            println(list5)
          }
        }
        
      • image-20230917104911022

    • package collection
      
      /**
       * 集合的计算函数
       */
      object Demo03 {
              
              
        def main(args: Array[String]): Unit = {
              
              
          var list = List[Int](1,3,4,5)
          println(list.sum)
          println(list.product)
          println(list.max)
          println(list.min)
          val list1 = list.sorted
          val list2 = list.sortBy((a: Int) => a)
          println(list1)
          println(list2)
          println(list.sortWith((a:Int,b:Int)=>a>b))
        }
      }
      
    • image-20230917104840160

9. Conversion implicite

Il étend les fonctions d'une classe afin que deux classes initialement indépendantes puissent s'appeler les méthodes de l'autre, et le contenu de conversion implicite sera automatiquement déclenché.

1. Fonction de conversion implicite

  • implicit def 函数名(类型):另外一个类型={
          
          
        如何创建另外一个类型
    }
    
  • Extension des fonctionnalités et des méthodes d'un type en convertissant le type d'entrée en type de sortie

  • package implicstudy
    
    class Demo {
          
          
      def run():Unit= {
          
          
    
      }
    }
    class Demo01{
          
          
      def call():Unit={
          
          
        println("call方法执行了")
      }
    }
    object Demo{
          
          
      def main(args: Array[String]): Unit = {
          
          
        implicit def test(demo:Demo):Demo01 ={
          
          
          new  Demo01()
        }
        var demo = new Demo()
        demo.call()
      }
    }
    
    
    package implicstudy
    
    class Test {
          
          
      def haha():Unit={
          
          
        println("haha执行了")
      }
    }
    object Test{
          
          
      def main(args: Array[String]): Unit = {
          
          
        implicit def xxx(a:Any):Test = {
          
          
          new Test
        }
        var a:Int = 1
        a.haha()
        var b:Boolean = true
        b.haha()
      }
    }
    
  • image-20230917111323682

  • image-20230917111343319

2. Paramètres de conversion implicites

  • On peut réaliser que lors de l'appel de paramètres, même si les paramètres n'ont pas de valeurs par défaut, la fonction peut être appelée sans les transmettre.

  • Si vous utilisez des paramètres de conversion implicites, vous devez effectuer deux étapes

    • 1. Tout d'abord, vous devez déclarer les paramètres de la fonction comme paramètres de conversion implicites.
      Nom de la variable : type de données
    • 2. Dans le périmètre de l'appel de fonction, déclarez une variable implicite du même type. Dans ce cas, lorsque la fonction est appelée, la fonction trouvera un paramètre du même type dans le périmètre et remplira automatiquement le nom de la variable implicite. : type de données =
      valeur
    • [Note] Il ne peut pas y avoir deux variables implicites du même type dans la même portée.
  • package implicstudy
    
    object Demo02 {
          
          
      def test(implicit name:String):Unit={
          
          
        println(name)
      }
    
      def main(args: Array[String]): Unit = {
          
          
        implicit var name = "zs"
        //implicit var name1 = "zs"
        test
      }
    }
    

3. Classe de conversion implicite

(1) Il possède un et un seul paramètre de construction

(2) Les classes implicites doivent être définies dans des « classes » ou des « objets compagnons » ou des « objets package », c'est-à-dire que les classes implicites ne peuvent pas être de niveau supérieur.

10. Le rôle de _ dans Scala

1. _ Dans la correspondance de modèles, _ représente d'autres situations qui ne correspondent pas. La situation par défaut est

2. Nom de la fonction _ : _ représente l'utilisation de la fonction dans son ensemble plutôt que d'appeler la fonction

3. Lors du guidage du colis, il a deux utilisations

  • 1. Importez toutes les classes sous un package
    import java.lang._
  • 2. Bloquez la classe spécifiée sous un certain package
    import java.util.{Arrays=>_}

4. Lors de la déclaration d'un attribut, la valeur de l'attribut peut être remplacée par _ : à ce stade, _ signifie attribuer une valeur par défaut à l'attribut.

Je suppose que tu aimes

Origine blog.csdn.net/weixin_57367513/article/details/132940577
conseillé
Classement