《大数据和人工智能交流》头条号向广大初学者新增C 、Java 、Python 、Scala、javascript 等目前流行的计算机、大数据编程语言,希望大家以后关注本头条号更多的内容。《大数据和人工智能》头条号方便有基础读者的同时照顾广大没入门的初学者。
(一)Scala的环境搭建及第一个Scala程序
Scala的安装环境包括jdk环境、scala语言环境、集成开发环境:
(1)jdk的下载
由于Scala语言基于Java虚拟机,所以得需要安装jdk,建议安装1.7以上版本,大家到
寻找相应的版本即可
(2)scala语言的安装包下载
输入网址,如图所示:
点击《DOWNLOAD》按钮即可到下载页面:
(3)集成开发环境IDE的下载
初学者建议大家使用eclipse,相信不少人学过Java所以使用起来比较顺手下载地址:http://www.scala-lang.org/download/
(4)InteliJIDEA的下载
InteliJIDEA也是一款非常不错的IDE开发环境,下载的地址,其下载页面如下所示:
1、windows环境搭建
scala所需软件下载后如下图所示:
(1)安装JDK
因为scala是给予JVM的所以必须安装JDK。JDK版本应该在JDK7以上。jdk分32位和64位,注意如果你安装的是32位,那么scala的IDE工具eclipse for scala也必须是32位的;如果你安装的是64位,那么scala的IDE工具eclipse for scala也必须是64位的
(2)安装32位jdk8版本
现在以32位的jdk-8u91-windows-i586.exe为例,windows环境必须是win7以上,否则有些功能不能使用。 jdk-8u91-windows-i586.exe的安装基本是傻瓜式的,这里不再给大家演示,安装后如图所示:
(3)配置jdk的环境变量
第一步:建立JAVA_HOME环境变量
我的电脑右键高级系统设置高级环境变量新建个JAVA_HOME输入JAVA_HOME的值,我这里是C:\Program Files (x86)\Java\jdk1.8.0_91,如图所示:
第二步:设置path环境变量,其值为%JAVA_HOME%\bin并放在最前面,和后面的值以分号分开
第三步:验证,打开命令行窗口输入java –version,出现下面结果为正确
2、安装scala
从官网下载安装包(如:scala-2.11.8.msi)进行安装,在bin目录下,执行scala.bat,会运行scala解释器
(1)安装也很简单,双击scala-2.11.8.msi
选择change—>change按钮next安装完毕,安装后进入Scala的bin目录,我这里是C:\Program Files (x86)\scala\bin
双击scala.bat文件,则弹出scala解释器:
我们运行一个最简单的程序:println("hello world"),如图所示输出hello world,搞定!
我们希望scala解释器能够到处运行,这时候我们可以设置环境变量:
SCALA_HOME= C:\Program Files (x86)\scala
Path=% SCALA_HOME %\bin
3、安装scala的IDE集成开发环境
强烈建议使用eclipse的集成开发环境开发scala,32位的集成环境已经下载,解压即可不需要安装,如图:
解压后
进入
双击
后界面如下:
至此,window环境下的scala环境安装完毕,以后我们将使用eclips for scala的IDE集成环境开发scala应用程序
4、第一个scala程序
下面我们将使用上述的eclipse开发scala的第一个程序,输出大名鼎鼎的"Hello World":
第一步:打开eclipse
第二步:新建scala项目demo
点击《Finish》按钮后,建立的项目如图所示:
第二步:新建个包test
Src右键NewPakagetest,如图:
第二步:选择test包NewScala Object输入Hello
代码如下:
package test
object Hello {
}
下面在Hello对象里面写第一程序,代码如下:
object Hello {
def main(args:Array[String]){
println("Hello World")
}
}
运行:
Hello.scala源文件右键Run AsScala Appication则在控制台输出:Hello World
(二)数据类型、变量、表达式、函数
1、数据类型
Scala会基于我们使用值的方式来确定其类型,这称为类型推断。数据类型有Int、Double、Boolean和String等
例如:var i=1+1.23结果为 i:Double = 2.23,意思是当Int加上Double的时候,结果变成了Double。Scala会执行大量的类型推断,如果遗漏了类型声明,那么Scala会帮你收拾残局
2、变量和常量
scala有两种变量val和var,val类似Java里面的final变量,一旦初始化了val就不能再被赋值。相反,var如同java的非final变量,可以在它的生命周期中被多次赋值
变量定义的语法:var name:type=initialization,也可以简写var name= initialization。在scala中,对于变量必须要初始化,不允许只声明而不初始化,例如下列程序:
object Hello {
def main(args:Array[String]){
var i:Int=100
var j=200;
val s:String="hello"
val ss="world"
println(i)
}
}
3、表达式
简单点的表达式val i=2;var j=10,我们还可以将表达式使用括号括起来。例如下列程序:
object Hello {
def main(args:Array[String]){
var c={
val a=1
val b=2
a*b
}
println(c)
}
}
其结果输出2
5、函数
在Scala中,函数的地位极其重要,函数不但可以是值还可以当做参数传递,下面我们学习函数的初步知识
函数的定义:
函数的定义以def开始,然后是函数名,跟着是括号带有冒号分隔符的参数列表。函数的每个参数都必须带有前缀冒号的类型标注,因为Scala编译器无法推断函数的参数类型
函数的定义如下图所示:
函数的定义及其调用示例如下:
示例-1
最简单的函数
object Hello {
def demo()={
println("hello world")
}
def main(args:Array[String]){
demo//调用
}
}
示例-2
object Hello {
def max(x:Int,y:Int):Int={
if(x>y)
x
else
y
}
def main(args:Array[String]){
val c=max(1,2)//调用
println(c)
}
}
注意:如果函数是递归的,那么函数结果的类型则必须被明确的说明
(三)Scala流程控制
1、选择结构
学习Scala最好有一门语言基础,否则个人不建议直接学Scala。这门语言可以是C/C++或者Java/PHP等,最好是Java,这时候你会不知不觉的将Scala的特性和Java比较,如果你熟悉Java,那么Scala的学习将十分的惬意
语法:
if(布尔值){
}else{
}
示例-1:
object Hello {
def main(args:Array[String]){
var flg ={2>1}//表达式返回结果布尔类型
if(flg==true){
println("I'm true")
}
}
}
示例-2:
object Hello {
def demo(i:Int):Int={
if(i>0){
100
}else{
-100
}
}
def main(args:Array[String]){
val j=demo(99)
println(j)
}
}
示例-3:
object Hello {
def demo()={
var c={
val a=100
var b=200
a+b
}
if(c==300){
println("It's ok");
}
}
def main(args:Array[String]){
demo
}
}
2、循环结构
(1)while循环
语法:
while(布尔值){
指令组
}
示例-1:计算1+2+3+….+100=?
object Hello {
def demo()={
var i=0;
var sum=0;
while(i<=100)
{
sum+=i;
i=i+1;
}
println("sum="+sum)
}
def main(args:Array[String]){
demo
}
}
(2)for循环
for(i <- 1.to(10) ){
println(i)
}
解释:
i无需声明类型,Scala会自动推断; 1.to(10)解释为在scala中基本数据类型也是对象,那么1这个对象有to方法表示从1-10闭区间,当然这种方式可以简写为:
for(i <- 1 to 10){
println(i)
}
但是你要明白原理。如果需要倒叙输出,则加上reverse,例如:
object Hello {
def demo()={
}
def main(args:Array[String]){
for(i <- 1 to 10 reverse){
println(i)
}
}
}
修改步长,例如:
for(i <- 1 to 10 ;if i%2==0){
println(i)
}
修改步长也可以采取如下形式:
for(i <- 1 to (10,2) ){
println(i)
}
上述将打印出1 3 5 7 9
(3)双重循环
for(i <- 1 to 10 ; j <- 11 to 20 ){
println("i="+i)//外层循环
println("j="+j)//内层循环
}
后面讲yield关键字和集合的时候可以将结果保存到集合中,例如:
object Hello {
def demo()={
}
def main(args:Array[String]){
var result=for(i <- 1 to 10 ) yield(i*2+1)
println(result)
}
}
程序输出结果为:Vector(3, 5, 7, 9, 11, 13, 15, 17, 19, 21)
(四)Scala的数组
1、数组的定义方式一
var 数组对象=new Array[数据类型](长度)
示例:
object Hello
{
def main(args:Array[String])
{
var arr=new Array[Int](3)
arr(0)=1
arr(1)=2
arr(2)=3
for(i <- arr)
{
println(i)
}
}
}
2、数组的定义方式二
var 数组对象=Array[数据类型](数据1, 数据2, 数据3)
示例:
object Hello
{
def main(args:Array[String])
{
var arr=Array[Int](1,2,3)
for(i <- arr)
{
println(i)
}
}
}
数据的数据类型也可以是混合的,例如:
object Hello
{
def main(args:Array[String])
{
var arr=Array(1,2,3,"abc")
for(i <- arr)
{
println(i)
}
}
}
3、数组的常用属性
object Hello
{
def main(args:Array[String])
{
var arr=Array[Int](1,2,3)
println(arr.length)//求数组的长度
println(arr.max)//求数组最大值
println(arr.min)//求数组最小值
println(arr.sum)//求数组元素的和
println(arr.mkString(";")) //将元素拼接成字符串
}
}
数组也可以根据长度迭代输出元素,如下所示:
object Hello
{
def main(args:Array[String])
{
var arr=Array[Int](1,2,3)
for( i <- 0 until arr.length )
{
println(arr(i))
}
}
}
4、变长数组
有时候我们需要为数组新增一个元素,这时候我们需要使用变长数组ArrayBuffer,这时候我们需要引入相应的类包import scala.collection.mutable.ArrayBuffer。
新增一个元素的语法为:数组+=元素,同理减少个元素为:数组-=元素,例如:
import scala.collection.mutable.ArrayBuffer
object Hello
{
def main(args:Array[String])
{
var arr=ArrayBuffer[Int](1,2,3)
arr+=66//新增个元素为66
for(i <- arr)
{
println(i)
}
arr-=3 //将数组元素为3的移除
for(i <- arr)
{
println(i)
}
}
}
也可以将一个数组的元素添加到另一个数组。格式为:数组1++=数组2,意思是将数组2的元素添加到数组1,例如:
object Hello
{
def main(args:Array[String])
{
var arr1=ArrayBuffer[Int](1,2,3)
var arr2=ArrayBuffer[Int](4,5,6)
arr1++=arr2 //将数组arr2的元素添加到arr1
for(i <- arr1)
{
println(i)
}
}
}
将数组变成变长数组如下:
object Hello
{
def main(args:Array[String])
{
var arr1=Array[Int](1,2,3)
var arr2=arr1.toBuffer //将arr1转化为变长数组
arr2+=88 //向数组arr2中新增个元素arr2
for(i <- arr2)
{
println(i)
}
}
}
将变长数组转化成非变长数组方法如下:
var arr1=ArrayBuffer[Int](1,2,3)//变长数组
arr1+=99
for(i <- arr1)
{
println(i)
}
var arr2=arr1.toArray //非变长数组
5、变长数组常用的方法
(1)trimEnd(n:Int)方法:删除后面n个元素
object Hello
{
def main(args:Array[String])
{
var arr=ArrayBuffer[Int](1,2,3,4,5,6)//变长数组
arr.trimEnd(3)
for(i <- arr)
{
println(i)
}
}
}
(2)insert方法:插入数组元素
示例-1:
import scala.collection.mutable.ArrayBuffer
object Hello
{
def main(args:Array[String])
{
var arr=ArrayBuffer[Int](1,2,3,4,5,6)//变长数组
arr.insert(2, 999)//在索引值为2的位置插入999
for(i <- arr)
{
print(i+" ")
}
}
}
上述程序输出结果为:1 2 999 3 4 5 6
示例-2:
import scala.collection.mutable.ArrayBuffer
object Hello
{
def main(args:Array[String])
{
var arr=ArrayBuffer[Int](1,2,3,4,5,6)//变长数组
arr.insert(2, 777,888,999)//在索引值为2的位置插入777,888,999
for(i <- arr)
{
print(i+" ")
}
}
}
上述程序输出结果为:1 2 777 888 999 3 4 5 6
(3)remove:移除数组元素
示例-1:
import scala.collection.mutable.ArrayBuffer
object Hello
{
def main(args:Array[String])
{
var arr=ArrayBuffer[Int](1,2,3,4,5,6)//变长数组
arr.remove(2)//删除索引值为2的元素
for(i <- arr)
{
print(i+" ")
}
}
}
上述程序输出结果为:1 2 4 5 6
示例-2:
import scala.collection.mutable.ArrayBuffer
object Hello
{
def main(args:Array[String])
{
var arr=ArrayBuffer[Int](1,2,3,4,5,6,7,8,9)//变长数组
arr.remove(2,3)//删除索引值为2后面的3个元素
for(i <- arr)
{
print(i+" ")
}
}
}
上述程序输出结果为:1 2 6 7 8 9
(4)对变长数组进行排序
object Hello
{
def main(args:Array[String])
{
var arr=ArrayBuffer[Int](6,1,68,99,12)//变长数组
//使用sorted属性对数组排序
val arr_new= arr.sorted
for(i <- arr_new)
{
print(i+ " ")
}
}
}
上述程序输出结果为:1 6 12 68 99
(5)对非变长数组进行排序
object Hello
{
def main(args:Array[String])
{
var arr=Array[Int](6,1,68,99,12)//变长数组
//使用scala.util.Sorting.quickSort对数组排序
scala.util.Sorting.quickSort(arr)
for(i <- arr)
{
print(i+ " ")
}
}
}
6、使用yield关键字对数组元素进行运算
例如,下列的例子:
import scala.collection.mutable.ArrayBuffer
object Hello
{
def main(args:Array[String])
{
var arr=ArrayBuffer[Int](1,2,3,4,5,6,7,8,9)//变长数组
//把数组的每个元素乘以2,返回的是一个新数组,也可以进行复//杂的运算
val arr_new= for(i <- arr) yield i*2
for(i <- arr_new)
{
print(i+ " ")
}
}
}
上述程序输出结果为:2 4 6 8 10 12 14 16 18
7、二维数组
如有下列二维阵列
那么,二维数组的使用如下所示:
import scala.collection.mutable.ArrayBuffer
object Hello
{
def main(args:Array[String])
{
var arr=Array.ofDim[Int](3, 3)//定义3行3列的二维数组
//第1行
arr(0)(0)=1
arr(0)(1)=2
arr(0)(2)=3
//第2行
arr(1)(0)=4
arr(1)(1)=5
arr(1)(2)=6
//第3行
arr(2)(0)=7
arr(2)(1)=8
arr(2)(2)=9
for(i <- 0 to 2 )
{
for(j <- 0 to 2)
{
print(" "+arr(i)(j))
}
println//换行
}
}
}
上述程序输出结果为:
1 2 3
4 5 6
7 8 9
(五)Scala中的集合List
Scala的List不能有多种数据类型混入组成,只能是要么全是字符串要么全是整数类型等。Scala中的List其实只有2部分构成,一个是头(第一个元素),然后是尾(其它元素)。List的使用如下:
object Demo {
def main(args:Array[String]){
val list=List("aaa","bbb","ccc")
for(i <- list)
{
println(i)
}
}
}
List也有一些方法如上述例子中list.isEmpty、 list.head等,下面我们详细说下:
(1)List的isEmpty、head、length等方法
object Hello {
def main(args:Array[String])={
val list=List("aaa","bbb","ccc");
//1、判断list元素是否为空
println("isEmpty==="+list.isEmpty)
//2、获取头元素
println("head==="+list.head)
//3、获取数组元素长度
println("length==="+list.length)
//4、获取最后一个元素
println("last==="+list.last)
//5、init指的是除了最后一个元素之外其它所有元素
println("init==="+list.init)
//6、将数组反转
println("reverse==="+list.reverse)
}
}
(2)使用:::合并集合
object Hello {
def main(args:Array[String])={
val list1=List(1,2,3);
val list2=List(4,5,6);
val list3=list1:::list2
for(i <- list3 ){
println(i)
}
}
}
(3)take 、drop、split等行为
object Hello {
def main(args:Array[String])={
val list1=List("aaa","bbb","ccc","ddd","eee");
//1、take指的是获取List对象中的某几个元素重新组成个List对象
val _list1=list1 take 3
for(i <- _list1)
{
println("_list1==="+i)
}
//2、、drop指的是删除List对象中的某几个元素剩下的重新组成个List对象
val list2=List("aaa","bbb","ccc","ddd","eee");
val _list2=list2 drop 3
for(i <- _list2)
{
println("_list2==="+i)
}
//splitAt将List从某点开始分割,返回一个元组,元组每个元素是个List对象
val list3=List("aaa","bbb","ccc","ddd","eee");
//把 _list3从索引值为2处分割成含有2个元素的元组
val _list3=list3 splitAt 2
//打印这个元组
println("_list3==="+_list3)
//获取元组中第1个元素的值并遍历,其为List对象
val v1=_list3._1
for(i <- v1)
{
println("v1=="+i)
}
//获取元组中第2个元素的值并遍历,其为List对象
val v2=_list3._2
for(i <- v2)
{
println("v2=="+i)
}
//获取List对象第3个索引的值
val list4=List("aaa","bbb","ccc","ddd","eee");
println("list4==="+list4(2))
}
}
(4)有关List对象的索引操作
object Hello {
def main(args:Array[String])={
val list=List("aaa","bbb","ccc","ddd","eee");
//1、获取list对象中所有索引值list.indices返回是Rang对象
val index=list.indices
for(i <- index)
{
println("index==="+i)
}
//2、使用zip进行拉链操作,返回Vector的对象
val v=list.indices zip list
//打印Vector对象v
println(v)
for(i <- v)
{
println(i) //每个值是个元组类型
}
}
}
(5)List和字符串之间常见的操作
object Hello {
def main(args:Array[String])={
// mkString
val list=List("aaa","bbb","ccc","ddd","eee");
//1、mkString用法一第1个参数表示开始元素,第2个参数表示元素间使用什么分
//隔,第3个元素表示结束元素
val s1=list.mkString("[", "-", "]")
println(s1)
//2、mkString用法二,只是使用每个元素的分隔符
val s2=list.mkString("-")
println(s2)
//3、mkString用法三,元素中间没有任何分隔符
val s3=list.mkString
println(s3)
//使用StringBuilder对象操作List对象
val buffer=new StringBuilder
list.addString(buffer, "[", "-", "]")
println(buffer.toString())
}
}
(6)List和数组、Iterator对象之间的关系
object Hello {
def main(args:Array[String])={
val list=List("aaa","bbb","ccc");
//1、List对象转化为数组对象
val arr1 = list.toArray
println(arr1)
//2、将数组对象转化为List对象
val arr2=Array(111,222,333)
val arr_list=arr2.toList
println(arr_list)
//3、List和Iterator对象
val it=list.toIterator
//it.next()为String类型
//val s1=it.next()
//println("s1="+s1)
//val s2=it.next()
//println("s2="+s2)
for(j <-it)
{
println(j)
}
}
}
(六)Scala的Map
1、map的定义形式1
语法:var map=Map[k数据类型,v数据类型](k1->v1,k2->v2)
迭代输出map数据的格式如下:
for( (k,v) <- map ){}
例如:
object Hello
{
def main(args:Array[String])
{
var map=Map[String,Int]("k1"->100,"k2"->200)
for((k,v) <- map)
{
println("k="+k+";v="+v)
}
}
}
默认使用的映射中的value是不可修改的,位于scala.collection.immutable包中。如果要修改,必须使用位于scala.collection.mutable包中的Map类型,例如:
object Hello
{
def main(args:Array[String])
{
var map=scala.collection.mutable.Map[String,Int]("k1"->100,"k2"->200)
map("k3")=300//新增个元素
for((k,v) <- map)
{
println("k="+k+";v="+v)
}
}
}
或者如下格式:
object Hello
{
def main(args:Array[String])
{
var map=scala.collection.mutable.Map[String,Int]("k1"->100,"k2"->200)
map+=("k3"->300)//新增个元素,同理删除元素使用map-=("k1")
for((k,v) <- map)
{
println("k="+k+";v="+v)
}
}
}
减少个元素代码如下:
object Hello
{
def main(args:Array[String])
{
var map=scala.collection.mutable.Map[String,Int]("k1"->100,"k2"->200)
map-=("k1")//新增个元素,同理删除元素使用map-=("k1")
for((k,v) <- map)
{
println("k="+k+";v="+v)
}
}
}
2、map定义形式2
map 数据结构定义也可以简写,如下所示:
object Hello
{
def main(args:Array[String])
{
var map=Map("k1"->100,"k2"->200)//简写
for((k,v) <- map)
{
println("k="+k+";v="+v)
}
}
}
3、使用getOrElse方法获取元素的值
有时候我们有 key获取value的时候,value的值可能没有,为了防止出现错误结果信息我们使用getOrElse(k,值2),意思是如果k对应的v存在,我们就返回v否则返回值2,例如
object Hello
{
def main(args:Array[String])
{
var map=Map("k1"->100,"k2"->200)
val v1=map.getOrElse("k1", 0)//k1的值存在为100
val v2=map.getOrElse("k3", 0)//k3的值不存在为则我们填0
println(v1)
println(v2)
}
}
结果输出为 100 0
(七)Scala函数详解
在Scala中,函数占据十分重要的地位,在前面我们简单介绍过函数的使用,下面我们主要看在Scala的函数式编程中,函数的各种使用情况。
1、 在函数里面定义函数
Scala支持在函数里面定义函数,如下例子所示:
object Demo
{
def f1(x:Int)={
println("进入函数体f1");
def f2(y:Int)={
println("进入函数体f2");
val z=x+y
z
}
val sum=f2(10)+20
sum
}
def main(args:Array[String]){
println(f1(100))
}
}
2、匿名函数
Scala函数非常大作用之一是函数可以当做变量使用,下面是匿名函数的使用方法
示例-1:
object Demo
{
def main(args:Array[String]){
var y=(x:Int)=>x+100 //匿名函数
println(y(10)) //匿名函数的调用
y=(x:Int)=>x+200 //函数像变量一样的使用
println(y(10)) //匿名函数的调用
}
}
示例-2:
object Demo
{
def main(args:Array[String]){
var str=(s:String)=>s+" world"
println(str("hello"))
}
}
3、高阶函数
将函数作为参数传递则称之为高阶函数,高阶函数用途相当的广泛,基本上我们在spark中大量采用高阶函数。
(1)将一个函数的实现传递给另外个函数
object Demo
{
def main(args:Array[String]){
val z=f2(1,2) //第二个函数的用法
println(z)
}
def f1(x:Int,y:Int)=x+y
def f2=f1 _ //将一个函数的实现传递给另外个函数
}
其中def f2=f1 _中的_代表占位符,意思是将一个函数实现传递给另外函数,必须的写语法规定。注意别丢掉空格
(2)高阶函数示例
现有函数def f1(x:Int,y:Int)=x+y,那么我们想定义个函数f2参数是接收一个函数,其定义格式为def f2(f:(Int,Int)=>Int),其中"f:(Int,Int)"代表2个参数类型, "=>Int"代表返回值类型,如下所示:
object Demo
{
def main(args:Array[String]){
def f1(x:Int,y:Int)=x+y
def f2(f:(Int,Int)=>Int)=f(1,2)+100
println(f2(f1)) //也可以写为println(f2(f1 _))
}
}
采取匿名函数形式如下:
object Demo
{
def main(args:Array[String]){
def f2(f:(Int,Int)=>Int)=f(1,2)+100
println(f2((x:Int,y:Int)=>x+y))
}
}
由于Scala可以自动进行类型推断,所以匿名函数的类型可以去掉,如下所示:
object Demo
{
def main(args:Array[String]){
def f2(f:(Int,Int)=>Int)=f(1,2)+100
println(f2((x,y)=>x+y))
}
}
(3)高阶函数简写
示例-1:
object Demo
{
def main(args:Array[String]){
def f2(f:(Int)=>Int)=f(100)+100
println(f2(x=>x+1))
}
}
该函数还可以简写,使用_代替,如下:
object Demo
{
def main(args:Array[String]){
def f2(f:(Int)=>Int)=f(100)+100
println(f2(_+1))
}
}
注意:简写的条件为匿名函数并且只有一行代码
示例-2:
下面是传递含有2个参数函数的简写
object Demo
{
def main(args:Array[String]){
def f2(f:(Int,Int)=>Int)=f(1,2)+100
println(f2((x,y)=>x+y))
}
}
上述程序还可以简写如下:
object Demo
{
def main(args:Array[String]){
def f2(f:(Int,Int)=>Int)=f(1,2)+100
println(f2(_ + _))
}
}
4、常见的高阶函数
下面列举了一些常见的高阶函数用法的示例:
object Demo
{
def main(args:Array[String]){
//示例-1
(1 to 10).map("*" * _).foreach(println _)
//示例-2
(1 to 10).filter(_ % 2==0).foreach(println)
//示例-3
println((1 to 100).reduceLeft(_ + _))
//示例-4
"Spark is the most exciting thing happening in big data today".split(" ")
.sortWith(_.length < _.length).foreach(println)
}
}
5、偏函数
调用函数可以说成是将函数应用于实参。如果传入所有的预期的参数,就完全应用了这个函数。如果只传入几个参数,就会得到一个偏应用函数。例如下列的例子:
object Demo
{
def log(date: Date, message: String) {
println(date + "----" + message)
}
def main(args:Array[String]){
val date = new Date
log(date, "message1")
log(date, "message2")
log(date, "message3")
}
}
示例中定义了一个log函数,在log函数中需要传入两个参数date和message。在之后又多次调用log函数,调用时使用了相同的date和不同的message。很显然,这里多次使用相同的date会让人有些小小的不耐烦。所以scala就提供了一个方案让人打消掉这小小的不耐烦:将log函数偏应用到date上,可以避免每次使用都要调用它,使用如下:
object Demo
{
def log(date: Date, message: String) {
println(date + "----" + message)
}
def main(args:Array[String]){
val f = log(new Date, _: String)
f("message1")
f("message2")
f("message3")
}
}
在示例代码中先将一个值绑定到date参数上,然后用"_"使第二个参数未绑定,这样就构成了一个偏应用函数。然后这个偏应用函数被存到f这个引用里。随后就可以使用不同的message来调用这个新的函数了。当创建偏应用函数时,Scala内部会创建一个新类,它有一个特殊的apply()方法。调用偏应用函数,实际上是调用这个apply方法
下面是更多偏函数的例子:
object Demo
{
def main(args:Array[String]){
//示例-1
val data = List(1,2,3,4,5,6)
data.foreach (println _) //方法1
data.foreach(x =>println(x)) //方法2
//不使用偏函数
def sum(a:Int,b:Int,c:Int) = a+ b+c
println(sum(1,2,3))
val fa = sum _
println(fa(2,3,4))
println(fa.apply(6, 6, 6)) //调用偏函数时候实际是调用新类的apply方法
val fb = sum(1,2,_:Int) //偏函数,只传递一个参数但必须指定类型
println(fb(3))
}
}
(八)Scala的面向对象
相对于JavaScala中的类更加简洁,与Java中的类不同Scala中的类还可以带参数。在Scala中,类并不声明为public、其属性必须初始化、其方法默认是共有的、无参数方法在调用的时候括号可以不写、声明无参数构造对象的时候括号也可以省略、声明无参数方法的时候括号也可以省略不写。下面是一个简单的没有参数的类:
object Hello
{
def main(args:Array[String])
{
var p=new Person()//或者var p=new Person
p.work() //或者p.work
println(p.getAge)
println(p.p_age)
}
}
class Person{
var p_name="lily"//属性值必须初始化
var p_age=20
def work() = println("People can work")
def getAge=p_age //该方法没有参数可以省略括号
}
1、scala的gettter和setter方法
scala在定义字段时使用var例如 var value=100(默认是共有的)默认提供setter和getter方法,对应名称为 value_= 和value,如果将value声明为私有的,那么setter和getter也是私有的,这时候读者如果依然想获取私有属性值,可自行定义方法进行控制
示例:
object Hello
{
def main(args:Array[String])
{
var demo=new Demo
var v=demo.value//getter方法
println(v)
demo.value_=(200)//setter方法
}
}
class Demo{
var value=100
}
注意的是当使用val定义字段时,scala不再提供对应的setter方法
示例:
class Demo{
private var value=100
def foo=value //自定义getter方法
}
2、this关键字
this关键字修饰的实行表示只能被当前对象引用,用法private [this] var v=100,例如:
class Demo{
private[this] var value=100
def foo(other:Demo)={
if(value>=other.value){//错误,this修饰的属性不能被其它对象引用
100
}
}
}
3、主构造器
在Scala中,每个类都有主构造器,主构造器的参数被编译成字段。主构造器定义的形式如下例子所示:
object Hello
{
def main(args:Array[String])
{
var p=new Person("","lily")
p.demo()
}
}
class Person(val id:String,val name:String){
def demo(){
println("身份证号是:"+id)
println("姓名是:"+name)
}
}
在没有参数的时候,会有个默认的无参数构造器,如下所示:
class Person(){
def demo(){
}
}
4、辅助构造器
辅助构造器的名称为this,每一个辅助构造器都必须有一个先前已经定义好的其它的主构造器或者辅助构造器的调用的开始,例如:
object Hello
{
def main(args:Array[String])
{
var p1=new Person() //由主构造器构造的对象
//由辅助构造器构造的对象
var p2=new Person("")
//由辅助构造器构造的对象
var p3=new Person("","lily")
}
}
class Person{
var pid:String=_ //不想赋值,使用下划线占位
def this(pid:String){
this()//调用主构造器
this.pid=pid
}
def this(pid:String,pname:String){
this("")//调用另外个辅助构造器
}
}
5、内部类
Java中的内部类从属于外部类,Scala中的内部类则不从属于外部类,内部类的使用和实例化也十分简单, 下面给了个例子说明其使用过程,我们就不再啰嗦其语法的定义了,如果你学过Java的内部类会十分感觉Scala内部类的惬意,所以强烈建议大家学习Java或者C++的一门面向对象语言
object Hello
{
def main(args:Array[String])
{
//声明外部类的实例
val outer=new Outer
val sum1=outer.sum()
println(sum1)
//声明内部类的实例
val inner=new outer.Inner(100)
val sum2=inner.foo()
println(sum2)
}
}
class Outer{
//内部类,计算从1+....+x=?
class Inner(val x:Int){
def foo()={
var i=0;
var sum=0;
while(i<=x)
{
sum=sum+i;
i=i+1;
}
sum
}
}
//外部类的方法demo
def sum()={
var in=new Inner(100)
val sum=in.foo()
sum
}
}
在内部类中,你可以像Java那样通过外部类.this的方式访问外部类this的引用,也可以使用如下的语法建立个该引用的别名,如下所示:
object Hello
{
def main(args:Array[String])
{
val outer1=new Outer("Scala_outer1")
val outer2=new Outer("Scala_outer2")
val inner1=new outer1.Inner("Scala_inner1")
val inner2=new outer2.Inner("Scala_inner2")
inner1.foo(inner1);
inner2.foo(inner2);
}
}
class Outer(val sname:String){
//outer是外部类的引用this
outer=>
class Inner(val sname:String){
def foo(inner:Inner)=println("外部类的sname:"+outer.sname
+" 内部类的sname:"+inner.sname
)
}
}
运行结果如下所示:
外部类的sname:Scala_outer1 内部类的sname:Scala_inner1
外部类的sname:Scala_outer2 内部类的sname:Scala_inner2
《大数据和人工智能交流》的宗旨
1、将大数据和人工智能的专业数学:概率数理统计、线性代数、决策论、优化论、博弈论等数学模型变得通俗易懂。
2、将大数据和人工智能的专业涉及到的数据结构和算法:分类、聚类 、回归算法、概率等算法变得通俗易懂。
3、最新的高科技动态:数据采集方面的智能传感器技术;医疗大数据智能决策分析;物联网智慧城市等等。
4、根据初学者需要会有C语言、Java语言、Python语言、Scala函数式等目前主流计算机语言。
5、根据读者的需要有和人工智能相关的计算机科学与技术、电子技术、芯片技术等基础学科通俗易懂的文章。
到此这篇scala function_编程的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!版权声明:
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若内容造成侵权、违法违规、事实不符,请将相关资料发送至xkadmin@xkablog.com进行投诉反馈,一经查实,立即处理!
转载请注明出处,原文链接:https://www.xkablog.com/scalabc/1826.html