上篇:Scala基础篇【上】
1、函数的各种写法
代码实现:
package org.apache.scala.day02
/**
* 描述:函数的各种写法
*/
object Demo008_Function {
//定义一个函数f1,参数是两个Int类型,返回值是一个Int类型
val f1 = (x: Int, y: Int) => x + y
//再定义一个函数f2
val f2 = (m: Int, n: Int) => m * n
val f3 = (x: Int) => x
// 函数其实可以简化(正确方式1)
val f4 = 1 + (_: Int)
// 函数其实可以简化(正确方式2)
val f5: Int => Int = 1 + _
def main(args: Array[String]): Unit = {
println(f1(2, 3))
println(f2(2, 3))
println(f3(3))
println(f4(4))
println(f5(4))
}
}
打印输出:
2、Scala的方法
def | 关键字,定义一个函数 |
max | 自定义的方法名 |
(x:Int, y:Int) | 方法名后小扩号中为参数列表 |
Int | 参数后的Int为方法返回值类型 |
{…} | 大扩号中为方法体 |
=: | 如果没有等号, 表示该方法的返回值是Unit |
Scala函数返回值可以不加return,默认函数体最后一条语句为返回值,函数体不指定返回值时,scala会根据实际类型进行类型推断
Unit关键字表示函数不存在返回值,相当于java中的void关键字
Scala每行语句结束后的分号可加可不加
代码实现:
package org.apache.scala.day02
/**
* 描述: Scala的方法
*/
object Demo008_Method {
def main(args: Array[String]): Unit = {
println(max(2, 3))
println(sub(4, 3))
println(sub1(4, 3))
println(decorate("Hello", "<<<", ">>>")) // <<<Hello>>>
println(decorate("Hello", "<<<")) // <<<Hello]
println(decorate(left = "<<<", str = "Hello", right = ">>>")) // 指定参数名,<<<Hello>>>
println(decorate("Hello", right = ">>>")) // [Hello>>>
println(sum(1, 2, 3, 4, 5))
println(sum(4, 5, 6, 7, 8, 9))
println(myPrint("huangbo"))
}
def max(x: Int, y: Int): Int = {
if (x > y) {
x
}
else {
y
}
}
// 如果没有return语句,那么方法中的最后一行就是返回值
def sub(a: Int, b: Int) = {
a - b
}
// 方法中的最后一行就是返回值,也可以使用return显示声明这就是返回值。
// 由于方法的定义中声明了,返回值就是Unit,所以sub1方法的返回值始终就是(),就算使用return进行返回也无济于事
def sub1(a: Int, b: Int): Unit = {
return a - b
}
// 如果定义一个方法,不需要返回值,那么可以省略 "="
def myPrint(s: String) {
println(s)
}
def myPrint1(s: String): Unit = {
println(s)
}
// 定义带默认参数的方法
def decorate(str: String, left: String = "[", right: String = "]") = left + str + right
// 定义变长参数方法
def sum(args: Int*): Int = {
var result = 0
for (arg <- args) result += arg
result
}
}
打印输出:
3、Scala的方法 和 函数
代码:
package org.apache.scala.day02
/**
* 描述: Scala的方法 和 函数
*/
object Demo009_MethodAndFunction {
//方法m1参数要求是一个函数,函数的参数必须是两个Int类型,返回值类型也是Int类型
def m1(f: (Int, Int) => Int): Int = f(2, 6)
// 定义一个需要两个Int类型参数的方法
def m2(x: Int, y: Int): Int = x + y
// 定义一个计算数据不被写死的方法
def m3(f: (Int, Int) => Int, x: Int, y: Int): Int = f(x, y)
// 定义一个函数f1,参数是两个Int类型,返回值是一个Int类型
val f1 = (x: Int, y: Int) => x + y
// 再定义一个函数f2
val f2 = (m: Int, n: Int) => m * n
// 定义一个传入函数的函数
val f3 = (f: (Int, Int) => Int, x: Int, y: Int) => f(x, y)
//main方法
def main(args: Array[String]) {
//调用m1方法,并传入f1函数
val r1 = m1(f1)
println(r1)
//调用m1方法,并传入f2函数
val r2 = m1(f2)
println(r2)
// 调用m3方法, 传入f1函数
val result1 = m3(f1, 2, 4)
println(result1)
// 调用m3方法,传入f2函数
val result2 = m3(f2, 2, 4)
println(result2)
// 调用m3方法, 传入m2方法作为参数
println(m3(m2, 2, 4))
// 调用f3函数, 传入f1函数
println(f3(f1, 3, 4))
}
}
打印输出:
4、函数和方法的使用
代码实现:
package org.apache.scala.day02
/**
* 描述: 函数和方法的使用
*/
object Demo010_MethodFunctionTrans {
// 定义方法
def m1(a: Int, b: Int): Int = {
a + b
}
def m2(f: Int => Int, a: Int) = {
f(a)
}
def m3(a: Int) = {
a + 1
}
val f1 = (x: Int) => x + 1
val ff = (f: Int => Int, x: Int) => f(x)
def main(args: Array[String]): Unit = {
// 把方法作为方法的参数
println(m2(m3, 4))
// 把函数作为方法的参数
println(m2(f1, 4))
// 函数当做函数的参数
println(ff(f1, 4))
// 方法当做函数的参数
println(ff(m3, 4))
}
}
打印输出:
在Scala中,比如:
def m(f : Int => Int, a:Int) = f(a)
val f1 = (x:Int) => x + 1
val f2 = (x:Int) => x * x
println(m(f1, 2))
println(m(f2, 2))
怎么让Java实现类似的功能?
难点:
- 使用装饰器设计模式来增强已有的组件List的功能: 定义一个map方法
- map方法中要传入的是一个自定的处理逻辑,也就相当于传入一个方法作为参数,但是Java不支持传入方法 只支持传入数据对象或者引用对象
解决方案:封装处理逻辑在对应的一个处理对象中的一个处理方法中, 不传入对象,但是可以传入一个处理对象
代码实现:
package org.apache.java;
import java.util.ArrayList;
import java.util.List;
public class Demo010_MyList {
private List<Integer> list;
public Demo010_MyList(List<Integer> list) {
this.list = list;
}
/**
* 如果需要什么样的逻辑,就在MyList1类中定义什么样的方法,这种方式不好维护和扩展
*/
public List<Integer> map1() {
// 返回一个新的List还是直接作用在原来的List之上,随自己指定
List<Integer> newList = new ArrayList<>();
for (Integer i : list) {
int newResult = i + 1;
newList.add(newResult);
}
return newList;
}
/**
* 其实表面上传入了方法, 但事实上, 传入了一个处理数据的逻辑
*/
public List<Integer> map(MapOperation o) {
List<Integer> newList = new ArrayList<>();
for (Integer i : list) {
// 这个地方,这句代码才是真正的处理原来的数据
// int newResult = i+1;
int newResult = o.operate(i);
newList.add(newResult);
}
return newList;
}
public List<Integer> reduce(ReduceOperator reduceOperator) {
return null;
}
/**
* 接口: 封装数据的逻辑, 成为接口, 就是为了统一规范
* 作用: 接收一个参数值, 返回一个值
*/
interface MapOperation {
Integer operate(Integer i);
}
/**
* 接口: 封装数据的逻辑, 成为接口, 就是为了统一规范
* 作用: 接收两个参数值, 返回一个值
*/
interface ReduceOperator {
Integer operate(Integer x, Integer y);
}
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
list.add(4);
list.add(5);
Demo010_MyList myList = new Demo010_MyList(list);
List<Integer> newList = myList.map(new MapOperation() {
@Override
public Integer operate(Integer i) {
return i * 100 - 5;
}
});
for (Integer i : newList) {
System.out.println(i);
}
}
}
打印输出:
5、数组
代码:
package org.apache.scala.day02
import scala.collection.mutable.ArrayBuffer
/**
* 描述:数组
*/
object Demo011_Array {
def main(args: Array[String]) {
//初始化一个长度为8的定长数组,其所有元素均为0
val arr1 = new Array[Int](8)
//直接打印定长数组,内容为数组的hashcode值
println(arr1)
//将数组转换成数组缓冲,就可以看到原数组中的内容了
//toBuffer会将数组转换长数组缓冲
println(arr1.toBuffer)
//注意:如果new,相当于调用了数组的apply方法,直接为数组赋值
//初始化一个长度为1的定长数组
val arr2 = Array[Int](10)
println(arr2.toBuffer)
//定义一个长度为3的定长数组
val arr3 = Array("hadoop", "storm", "spark")
//使用()来访问元素
println(arr3(2))
arr3(2) = "hive"
println(arr3.toBuffer)
println("-----------------------------------------------------------")
//
//变长数组(数组缓冲)
//如果想使用数组缓冲,需要导入import scala.collection.mutable.ArrayBuffer包
val ab = new ArrayBuffer[Int]()
//向数组缓冲的尾部追加一个元素
//+=尾部追加元素
ab += 1
//追加多个元素
ab += (2, 3, 4, 5)
//追加一个数组++=
ab ++= Array(6, 7, 7, 7)
//追加一个数组缓冲
ab ++= ArrayBuffer(8, 9)
// 追加一个List
ab ++= List(10, 11)
//打印数组缓冲ab
println(ab)
//在数组某个位置插入元素用insert
ab.insert(0, -1, 0)
//删除数组某个位置的元素用remove
ab.remove(8, 2)
println(ab)
}
}
打印输出:
6、集合数组
代码实现:
package org.apache.scala.day02
/**
* 集合数组
*/
object Demo011_ArrayFor {
def main(args: Array[String]) {
//初始化一个数组
val arr = Array(1, 2, 3, 4, 5, 6, 7, 8)
//增强for循环
for (i <- arr) {
println(i)
}
//使用to可以生成一个序列作为脚标
for (i <- (0 to arr.length - 1).reverse)
println(arr(i))
//好用的until会生成一个Range,reverse是将前面生成的Range反转
for (i <- (0 until arr.length).reverse)
println(arr(i))
//步长为2
for (i <- (0 until(arr.length, 2)).reverse)
println(arr(i))
}
}
打印输出:
7、数组的一些常用其他方法
代码实现:
package org.apache.scala.day02
import scala.collection.mutable.ArrayBuffer
import scala.util.Sorting
/**
* 描述: 数组的一些常用其他方法
*/
object Demo011_ArrayTest {
def main(args: Array[String]): Unit = {
val array = Array(4, 2, 7, 8, 1, 2, 2, 8, 8, 9)
val ab: ArrayBuffer[Int] = new ArrayBuffer[Int]()
ab += (4, 3, 5, 6, 2, 7, 1, 8)
val result11 = array.reduce((x: Int, y: Int) => x + y)
println(result11)
println(array.length)
println(array.max)
println(array.min)
println(array.sum)
println(array.mkString("-"))
println(array.mkString("<", ",", ">"))
println(array.filter((x: Int) => if (x % 2 == 0) true else false).toBuffer)
ab.trimStart(2)
println(ab)
ab.trimEnd(2)
println(ab)
println("-----------------1-----------------")
/**
* array的map和reduce操作
*/
val newArray: Array[Int] = array.map((x: Int) => x * 2)
println(newArray.toBuffer)
val newArray2: Int = array.reduce((x: Int, y: Int) => x + y)
println(newArray2)
println("-----------------2----------------")
/**
* fold操作
*/
array.foldLeft[Int](0)((init, value) => {
println(init, value);
init + value
})
println("------------------3----------------")
array.foldRight[Int](0)((init, value) => {
println(init, value);
init + value
})
val result: Int = array.fold(0)((x: Int, y: Int) => x + y)
println(result)
/**
* array求平均值
*/
val result2: (Int, Int) = array.map((x: Int) => (x, 1))
.reduce((x: (Int, Int), y: (Int, Int)) => (x._1 + y._1, x._2 + y._2))
println(result2._1 / result2._2.toDouble)
println("-----------------4-----------------")
/**
* 排序
*/
println(array.sorted.toBuffer)
println(array.sortBy(x => x).reverse.toBuffer)
println(array.sortWith((x: Int, y: Int) => x > y).toBuffer)
Sorting.quickSort(array)
println(array.toBuffer)
}
}
打印输出:
51
10
9
1
51
4-2-7-8-1-2-2-8-8-9
<4,2,7,8,1,2,2,8,8,9>
ArrayBuffer(4, 2, 8, 2, 2, 8, 8)
ArrayBuffer(5, 6, 2, 7, 1, 8)
ArrayBuffer(5, 6, 2, 7)
-----------------1-----------------
ArrayBuffer(8, 4, 14, 16, 2, 4, 4, 16, 16, 18)
51
-----------------2----------------
(0,4)
(4,2)
(6,7)
(13,8)
(21,1)
(22,2)
(24,2)
(26,8)
(34,8)
(42,9)
------------------3----------------
(9,0)
(8,9)
(8,17)
(2,25)
(2,27)
(1,29)
(8,30)
(7,38)
(2,45)
(4,47)
51
5.1
-----------------4-----------------
ArrayBuffer(1, 2, 2, 2, 4, 7, 8, 8, 8, 9)
ArrayBuffer(9, 8, 8, 8, 7, 4, 2, 2, 2, 1)
ArrayBuffer(9, 8, 8, 8, 7, 4, 2, 2, 2, 1)
ArrayBuffer(1, 2, 2, 2, 4, 7, 8, 8, 8, 9)
数组使用
package org.apache.scala.day02
/**
* 数组使用
*/
object Demo011_ArrayYield {
def main(args: Array[String]) {
//定义一个数组
val arr = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
//将偶数取出乘以10后再生成一个新的数组
val res = for (e <- arr if e % 2 == 0) yield e * 10
println(res.toBuffer)
//更高级的写法,用着更爽
//filter是过滤,接收一个返回值为boolean的函数
//map相当于将数组中的每一个元素取出来,应用传进去的函数
val r = arr.filter(_ % 2 == 0).map(_ * 10)
println(r.toBuffer)
}
}
打印输出:
9、集合
代码实现:
package org.apache.scala.day02
/**
* 集合
*/
object Demo012_ImmutableList {
def main(args: Array[String]) {
//创建一个不可变的集合
val list1 = List(1, 2, 3)
//将0插入到lst1的前面生成一个新的List
val list2 = 0 :: list1
val list3 = list1.::(0)
val list4 = 0 +: list1
val list5 = list1.+:(0)
println(list2, list3, list4, list5)
//将一个元素添加到lst1的后面产生一个新的集合
val list6 = list1 :+ 3
println(list6)
val list0 = List(4, 5, 6)
//将2个list合并成一个新的List
val list7 = list1 ++ list0
//将lst0插入到lst1前面生成一个新的集合
val list8 = list1 ++: list0
//将lst0插入到lst1前面生成一个新的集合
val list9 = list1.:::(list0)
println(list7)
println(list8)
println(list9)
}
}
打印输出: