系列文章目录
前言
这学期开了《Spark编程基础》,需要用到Scala语言,书上写的比较简单,本着学一门语言就应该尽量往深处学的想法,到图书馆借了一本《快学Scala》,英文名《Scala for the Impatient》,争取每周看完两章,并将相应练习写成博客。
练习
1.编写一段代码,将a设置为一个n个随机整数的数组,要求随机数介于0(包含)和n(不包含)之间。
首先引入scala.io.StdIn.readInt包
import scala.io.StdIn.readInt
object Test {
def main(args: Array[String]): Unit = {
val n: Int= readInt() //输入n的值
val a = new Array[Int](n) //建立元素个数为n的数组
for(i <- 0 until a.length){
a(i) = scala.util.Random.nextInt(n) //将随机数存入数组,随机数的范围为[0,n)
}
print(a.mkString(" ")) //将数组a中每个元素用空格隔开,转换成字符串进行输出
}
}
2.编写一个循环,将整数数组中相邻的元素置换。例如,Array(1, 2, 3, 4, 5)经过置换后变为Array(2, 1, 4, 3, 5)。
object Test {
def main(args: Array[String]): Unit = {
val a = Array[Int](1,2,3,4,5,6,7,8,9,10) //建立数组a
println(a.mkString("|")) //将数组a中每个元素用"|"隔开,转换成字符串进行输出,输出后换行
//相邻元素进行置换
for(i <- 0 until a.length by 2 if i < a.length-1 ){ //守护if i < a.length-1 是防止数组a(i + 1)发生越界
val temp = a(i)
a(i) = a(i + 1)
a(i + 1) = temp
}
print(a.mkString("|")) //将数组a中每个元素用"|"隔开,转换成字符串进行输出
}
}
3.重复前一个练习,不过这一次生成一个新的值交换过的数组。用for/yield。
object Test {
def main(args: Array[String]): Unit = {
val a = Array[Int](1,2,3,4,5,6,7,8,9,10,11) //建立数组a
println(a.mkString("|")) //将数组a中每个元素用"|"隔开,转换成字符串进行输出,输出后换行
//相邻元素进行置换
//总体思路:设n个元素,前n-1个元素按照下标i为奇数还是偶数,i为偶数便添加为b(i + 1);i为奇数便添加为b(i - 1)
// 随后单独对最后一号元素进行判断,若下标为偶数,则a中含有奇数个元素,其没有相邻元素进行置换,直接添加为b(n-1)
// 若下标为奇数,则a中含有偶数个元素,其相邻元素为前一号元素,将其前一号元素添加为b(n-1)
val b = for(i <- 0 until a.length) yield {
if(i < a.length - 1){
if(i % 2 == 0)
a(i + 1)
else
a(i - 1)
}
else{
if(i % 2 == 0)
a(i)
else
a(i - 1)
}
}
print(b.mkString("|")) //将数组b中每个元素用"|"隔开,转换成字符串进行输出
}
}
a中有偶数个元素
a中有奇数个元素
4.给定一个整数数组,产出一个新的数组,包含原数组中的所有正值,以原有顺序排列,之后的元素是所有零或负值,以原有顺序排列。
import scala.collection.mutable.ArrayBuffer
object Test {
def main(args: Array[String]): Unit = {
val a = Array[Int](3,1,-1,4,2,5,0,-4,0,1,3,-2,0) //建立数组a
println("a = " + a.mkString(" ")) //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
//总体思路:遍历一次数组,将正数按顺序添加到一个ArrayBuffer中;
// 再次遍历数组,将0和负数按顺序添加到ArrayBuffer中,再将ArrayBuffer转为Array
val b = ArrayBuffer[Int]()
for(i <- 0 until a.length if a(i) > 0)
b += a(i)
for(i <- 0 until a.length if a(i) <= 0)
b += a(i)
val c = b.toArray
print("b = " + c.mkString(" ")) //将数组c中每个元素用" "隔开,转换成字符串进行输出
}
}
5.如何计算Array[Double]的平均值?
object Test {
def main(args: Array[String]): Unit = {
val a = Array[Double](3,1,-1,4,2,5,0,-4,0,1,3,-2,0) //建立数组a
println("a = " + a.mkString(" ")) //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
println("a.avg = " + a.sum / a.length) //a中数值总数除以a中元素个数
}
}
6.如何重新组织Array[Int]的元素将它们以反序排列?对于ArrayBuffer[Int]你又会怎么做呢?
Array[Int]借助中间变量进行置换
object Test {
def main(args: Array[String]): Unit = {
val a = Array[Int](3,1,-1,4,2,5,0,-4,0,1,3,-2,0,1) //建立数组a
println("a = " + a.mkString(" ")) //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
for(i <- 0 until a.length / 2){
val temp = a(i)
a(i) = a(a.length-1-i)
a(a.length-1-i) = temp
}
println("a = " + a.mkString(" ")) //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
}
}
ArrayBuffer[Int]可以直接调用reverse函数进行转置
import scala.collection.mutable.ArrayBuffer
object Test {
def main(args: Array[String]): Unit = {
var a = ArrayBuffer[Int](3,1,-1,4,2,5,0,-4,0,1,3,-2,0,1) //建立数组缓冲a
println("a = " + a.mkString(" ")) //将数组缓冲a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
a = a.reverse
println("a = " + a.mkString(" ")) //将数组缓冲a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
}
}
在使用时发现,Array也有reverse函数可以调用
7.编写一段代码,产出数组中的所有值,去掉重复项。(提示:查看Scaladoc)
查看Scaladoc后找到相关方法distinct
object Test {
def main(args: Array[String]): Unit = {
val a = Array[Int](3,1,-1,4,2,5,0,-4,0,1,3,-2,0,1) //建立数组a
println("a = " + a.mkString(" ")) //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
println("a = " + a.distinct.mkString(" ")) //将数组a中每个元素用" "隔开,转换成字符串进行输出,输出后换行
}
}
8.重新编写3.4节结尾的示例。收集负值元素的下标,反序,去掉最后一个下标,然后对每一个下标调用a.remove(i)。比较这样做的效率和3.4节中另外两种方法的效率。
3.4示例为
val a = Array(2, 3, 5, 7, 11)
var first = true
val indexes = for (i <- 0 until a.length if first || a(i) >= 0) yield {
if (a(i) < 0) first = false;
i
}
for(j <- 0 until indexes.length)
a(j) = a (indexes(j))
a.trimEnd(a.length - indexes.length)
重新编写后为:
import scala.collection.mutable.ArrayBuffer
object Test {
def main(args: Array[String]): Unit = {
val a = ArrayBuffer[Int](2, -3, 5, 7, -11, -1, 0, 1,-2)
println("a:" + a.mkString(" ")) //将初始的数组缓冲a输出
//调用currentTimeMillis()设置时间戳,两时间戳相减约等于noName运行时间
val tm1 = System.currentTimeMillis()
noName(a)
val tm2 = System.currentTimeMillis()
println("用时:" + (tm2-tm1)) //将用时输出
println("a:" + a.mkString(" ")) //输出只剩第一个负数的数组缓冲a
}
def noName(a: ArrayBuffer[Int]): Unit = {
//将各负数下标记录
var indexes = for(i <- 0 until a.length if a(i) < 0) yield i
//将下标反序,并去除最后一个下标
indexes = indexes.reverse.dropRight(1)
//对每一个下标调用a.remove()方法
for(i <- 0 until indexes.length)
a.remove(indexes(i))
}
}
再求出另外两种方法的时间效率
import scala.collection.mutable.ArrayBuffer
object Test {
def main(args: Array[String]): Unit = {
val a = ArrayBuffer[Int](2, -3, 5, 7, -11, -1, 0, 1,-2)
println("a:" + a.mkString(" "))
//调用currentTimeMillis()设置时间戳,两时间戳相减约等于noName运行时间
val tm1 = System.currentTimeMillis()
noName(a)
val tm2 = System.currentTimeMillis()
println("用时:" + (tm2-tm1))
println("a:" + a.mkString(" "))
}
def noName(a: ArrayBuffer[Int]): Unit = {
var first = true
var n = a.length
var i = 0
while( i < n) {
if (a(i) >= 0) i += 1
else{
if(first) {
first = false;
i += 1
}
else{
a.remove(i);
n -= 1
}
}
}
}
}
import scala.collection.mutable.ArrayBuffer
object Test {
def main(args: Array[String]): Unit = {
val a = ArrayBuffer[Int](2, -3, 5, 7, -11, -1, 0, 1,-2)
println("a:" + a.mkString(" "))
//调用currentTimeMillis()设置时间戳,两时间戳相减约等于noName运行时间
val tm1 = System.currentTimeMillis()
noName(a)
val tm2 = System.currentTimeMillis()
println("用时:" + (tm2-tm1))
println("a:" + a.mkString(" "))
}
def noName(a: ArrayBuffer[Int]): Unit = {
var first = true
val indexes = for (i <- 0 until a.length if first || a(i) >= 0) yield {
if(a(i) < 0) first = false;
i
}
for(j <- 0 until indexes.length)
a(j) = a(indexes(j))
a.trimEnd(a.length - indexes.length)
}
}
9.创建一个由java.util.TimeZone.getAvailableIDs返回的时区集合,判断条件是它们在美洲。去掉"America/"前缀并排序。
涉及到比对"America/“ 需要使用Array类中的startswith()方法
object Test {
def main(args: Array[String]): Unit = {
val times = java.util.TimeZone.getAvailableIDs()
//去除含有"America/"的数组元素
var select = for(member <- times if member.startsWith("America/") != true) yield member
select = select.sorted //将去除"America/"后的数组进行排序
println(times.mkString)
println(select.mkString)
}
}
10.引入java.awt.datatransfer._并构建一个类型为SystemFlavorMap类型的对象:
val flavors = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]
然后以DataFlavor.imageFlavor为参数调用getNativesForFlavor方法,以Scala缓冲保存返回值。(为什么用这样一个晦涩难懂的类?因为在Java标准类库中很难找得到使用java.util.List的代码。)
import java.awt.datatransfer._
object Test {
def main(args: Array[String]): Unit = {
//构建对象
val flavors = SystemFlavorMap.getDefaultFlavorMap().asInstanceOf[SystemFlavorMap]
//调用getNativesForFlavor()方法,将返回结果转为Array,再转为Buffer
val buffer = flavors.getNativesForFlavor(DataFlavor.imageFlavor).toArray.toBuffer
println(buffer)
}
}