简介

在本章中,我们将会学到如何在scala中操作数组。

1、定长数组

// 初始化长度为10的定长数组,每一个元素的值为0
val nums = new Array[Int](10)
// nums: Array[Int] = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0)

// 初始化长度为10的定长数组,每一个元素的值为null
scala> val str2 = new Array[String](10)
str2: Array[String] = Array(null, null, null, null, null, null, null, null, null, null)


scala> val num3 = Array(1,2,3)
num3: Array[Int] = Array(1, 2, 3)

scala> num3(0) = 4

scala> num3
res5: Array[Int] = Array(4, 2, 3)

在JVM中,Scala的Array以Java数组的方式实现。

2、变长数组

Java中有ArrayList,C++有vector,而Scala中为ArrayBuffer。

// 首先导入包
scala> import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.ArrayBuffer

scala> val a = ArrayBuffer[Int]()
a: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer()

scala> a += 1
res0: a.type = ArrayBuffer(1)

scala> a(0)
res2: Int = 1

scala> a += (2,3,4,5)
res4: a.type = ArrayBuffer(1, 2, 3, 4, 5)

// +=  追加元素
// ++= 追加集合
scala> a ++= Array(2,3,4)
res7: a.type = ArrayBuffer(1, 2, 3, 4, 5, 2, 3, 4)

// trimEnd 移除最后的5个元素
scala> a.trimEnd(5)

scala> a
res9: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 3)

以上都是基于尾部的操作,是比较搞笑的操作方式。也可以在任意位置进行操作。

// 不用指定类型(类型推断)
scala> val a = ArrayBuffer(1,1,1)
// ArrayBuffer(1, 1, 1)

// 在下标2处插入100
scala> a.insert(2,100)
// ArrayBuffer(1, 1, 100, 1)

// 插入多个值
scala> a.insert(0,200,300,400)
// ArrayBuffer(200, 300, 400, 1, 1, 100, 1)

// 移除元素
scala> a.remove(0)
// ArrayBuffer(300, 400, 1, 1, 100, 1)

// 移除多个元素,第二个参数的意思是移除多少个元素
scala> a.remove(0,3)
// ArrayBuffer(1, 100, 1)

可变与不可变数组之间的转换

scala> a.toArray
res8: Array[Int] = Array(1, 100, 1)

scala> res8.toBuffer
res9: scala.collection.mutable.Buffer[Int] = ArrayBuffer(1, 100, 1)

3、遍历数组与数组缓冲

遍历数组与数组缓冲的代码都是一样的,不像java和C++一样需要区别对待。

scala> for(i <- 0 until res8.length) println(s"$i : ${res8(i)}")
0 : 1
1 : 100
2 : 1

scala> for(i <- 0 until res9.length) println(s"$i : ${res9(i)}")
0 : 1
1 : 100
2 : 1
-------------------------------
// 重新创建一个集合
scala> val b = Array(1,2,3,4)
b: Array[Int] = Array(1, 2, 3, 4)


// 跳步为2的遍历
scala> for(i <- 0 until b.length by 2) println(b(i))
1
3

// 尾端遍历
scala> for(i <- (0 until b.length).reverse) println(b(i))
4
3
2
1

// 直接获取数组元素遍历
scala> for(ele <- b) println(ele)
1
2
3
4

4、数组转换

// yield
scala> val c = Array(1,2,3,4)
c: Array[Int] = Array(1, 2, 3, 4)

scala> val result = for (ele <- c) yield 2 * ele
result: Array[Int] = Array(2, 4, 6, 8)

// 或者使用map
scala> val result2 = c.map(ele => ele * 2)
result2: Array[Int] = Array(2, 4, 6, 8)

5、常用算法


scala> val a = Array(1,2,4,3,5)
a: Array[Int] = Array(1, 2, 4, 3, 5)

// 一些常用操作
scala> a.sum
res28: Int = 15

scala> a.min
res30: Int = 1

scala> a.max
res31: Int = 5

// 排序
scala> a.sorted
res37: Array[Int] = Array(1, 2, 3, 4, 5)

// 指定方式排序(sortWith方法只可适用于变长数组)
scala> val s = ArrayBuffer(1,2,4,3,5)
s: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(1, 2, 4, 3, 5)

scala> s.sortWith(_ > _)
res39: scala.collection.mutable.ArrayBuffer[Int] = ArrayBuffer(5, 4, 3, 2, 1)

6、打印数组元素

scala> a.mkString(",")
res0: String = 1,2,3,4,5

// 重载方法,设置两边的字符
scala> a.mkString("<",",",">")
res1: String = <1,2,3,4,5>

7、解读Scaladoc

8、多维数组

和Java一样,都是通过数组的数组实现多维数组。ofDim方法。

scala> val matrix = Array.ofDim[Double](3,4)
matrix: Array[Array[Double]] = Array(Array(0.0, 0.0, 0.0, 0.0), Array(0.0, 0.0, 0.0, 0.0), Array(0.0, 0.0, 0.0, 0.0))

scala> matrix(0)(0)=1

scala> matrix
res4: Array[Array[Double]] = Array(Array(1.0, 0.0, 0.0, 0.0), Array(0.0, 0.0, 0.0, 0.0), Array(0.0, 0.0, 0.0, 0.0))

9、与Java的互操作

val command = ArrayBuffer("ls","-al")
val pb = new ProcessBuilder(command) // Scala到Java的转换

val cmd: Buffer[String] = pb.command() // Java到Scala的转换

L、练习

package com.zhaoyi.ch3

import java.util.TimeZone

import scala.util.Random

object Practice {

  // 练习1:编写一段代码,将a设置为n个随机整数组成的数组,要求随机数介于[0,n)之间。
  def exercise1(n: Int): Array[Int] ={
    val random = new Random()
    // scala.collection.immutable.IndexedSeq[Int]
    val result = for (i <- 0 to n) yield random.nextInt(n)
    result.toArray
  }

  // 练习2:编写一个循环,将整数数组中的相邻的元素置换。例如,Array(1,2,3,4,5),经过置换之后变为(2,1,4,3,5)
  def exercise2(arr: Array[Int]): Array[Int] ={
    for (i <- 0 until arr.length - 1 by 2){
      // 相邻元素交换之
      val temp = arr(i);
      arr(i) = arr(i + 1);
      arr(i + 1) = temp;
    }
    arr
  }

  // 练习3:重复前一个练习,不过这一次生成一个新的值交换过的数组,使用 for/yield
  def exercise3(arr: Array[Int]): Array[Int] ={
    val newArr = for (i <- 0 until arr.length) yield {
      // 如果当前是置换对的第二个元素,那么当前位置的元素一定是旧数组的上一个元素
      if(i % 2 == 1){
        arr(i-1)
      } else{// 若这是置换对的第一个元素,那么他的值需要考虑两种情况:后面有没有元素:有的话,返回后面一个元素;没有的话,返回自己即可
        if(i == arr.length - 1) arr(i) else arr(i + 1)
      }
    }
    newArr.toArray
  }

  // 练习4:给定一个整数数组,产出一个新的数组,包含原数组中的所有正值,以原有的顺序输出;之后的元素所有的0和负值,以原有的顺序排列。
  def exercise4(arr: Array[Int]): Array[Int] ={
    arr.filter(num => num > 0).map(a => a) ++ arr.filter(num => num <= 0).map(a => a)
  }

  // 练习5:如何计算Array[Double]的平均值
  def exercise5(arr: Array[Double]): Double ={
    arr.sum / arr.length
  }

  // 练习6:如何重新组织Array[Int]的元素将他们以反序排列?对于ArrayBuffer[Int]又该怎么做呢?
  // 解答:Array[Int]可以直接调用sorted方法排序;而对于ArrayBuffer,则需要使用sortWith

  // 练习7:给定一个数组,产出数组中的所有值,去掉重复项。
  def exercise7(arr:Array[Int]): Array[Int] = {
    arr.distinct
  }

  // 练习8:给定一个缓冲数组,移除该数组除第一次出现的负数以外的所有负数。
  def exercise8(arr:Array[Int]): Array[Int] = {
    var first = true;
    arr.filter(num => {
      if(num >= 0 ) true
      else {
        if(first) {
          first = false
          true
        }else false
      }
    });
  }

  // 练习9:跳过

  // 练习10:创建一个由java.util.TimeZone.getAvailableIds返回的时区集合,判断条件是他们在美洲,去掉America/前缀并排序
  def exercise10(): Unit = {
    val prefix = "America/";
    val timeZone = TimeZone.getAvailableIDs();
    val AmericaZones = for (zone <- timeZone if zone.startsWith(prefix)) yield {
      // 去掉前缀America/
      zone.substring(prefix.length);
    }
    val soredZone = AmericaZones.sorted
    soredZone.foreach(z => println(z));
  }


  def main(args: Array[String]): Unit = {
    println("exercise 1(n = 10): " + exercise1(10).mkString(","))
    println("exercise 2(Array(1,2,3,4,5)): " + exercise2(Array(1,2,3,4,5)).mkString(","))
    println("exercise 3(Array(1,2,3,4,5)): " + exercise3(Array(1,2,3,4,5)).mkString(","))
    println("exercise 4(Array(-1,2,-3,4,5,0)): " + exercise3(Array(-1,2,-3,4,5,0)).mkString(","))
    println("exercise 5(Array(1,2,3,4,5,6,7,8,9,10)) mean is : " + exercise5(Array(1,2,3,4,5,6,7,8,9,10)))

    println("exercise 7(Array(1,1,2,2,2,3,3,4)) distinct is: " + exercise7(Array(1,1,2,2,2,3,3,4)).mkString(","))

    println("exercise 8(Array(5,4,3,2,1,0,-1,-2,-3,1,2,-1,-2)): " + exercise8(Array(5,4,3,2,1,0,-1,-2,-3,1,2,-1,-2)).mkString(","))

    println("exercise 10: " + exercise10())

  }
}
02-23 19:42