Scala基础篇【中】

本文深入介绍了Scala中的函数、方法的定义与使用,包括不同写法、参数传递和返回值类型。同时,探讨了Scala数组、集合数组及其操作,如map、reduce等。此外,还展示了如何在Java中模拟类似Scala的函数式编程特性,通过装饰器模式增强List功能。文章最后讨论了不可变集合List的创建、组合和操作。
摘要由CSDN通过智能技术生成

上篇: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)
  }
}


打印输出:

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值