scala学习笔记 - scala与java集合的互操作

25 篇文章 0 订阅
15 篇文章 2 订阅

JavaConversions对象提供了用于在Scala和Java集合之间来回转换的一组方法。
给目标值显式地指定一个类型来触发转换 例如:

import scala col lec ti JavaConversions._
val props: scala.collection.mutable.Map[String, String] = System .getProperties()

如果你担心那些不需要的隐式转换也被引人的话,只引入需要的即可 例如:

import scala.collection.JavaConversions.propertiesAsScalaMap

注意这些转换产出的是包装器,让你可以使用目标接口来访问原本的值。举例来说,如果你用

val props: scala.collection.mutable.Map[String, String] = System.getProperties()

那么props就是一个包装器,其方法将调用底层的Java对象。如果你调用

props ("com.horstmann.scala")= "impatient"

那么包装器将调用底层Properties对象的put("com.horstmann.scala", "impatient")
从Scala集合到Java集合的转换:

隐式函数从scala.collection的类型到java.util的类型
asJavaCollectionIterableCollection
asJavaIterableIterableIterable
asJavaIteratorIteratorIterator
asJavaEnumerationIteratorEnumeration
seqAsJavaListSeqList
mutableSeqAsJavaListmutable.SeqList
bufferAsJavaListmutable.BufferList
setAsJavaSetSetSet
mutableSetAsJavaSetmutable.SetSet
mapAsJavaMapMapMap
mutableMapAsJavaMapmutable.MapMap
asJavaDictionaryMapDictionary
asJavaConcurrentMapmutable.ConcurrentMapconcurrent.ConcurrentMap

从Java集合到Scala集合的转换:

隐式函数从java.util的类型到scala.collection的类型
collectionAsScalaIterableCollectionIterable
iterableAsScalaIterableIterableIterable
asScalaIteratorIteratorIterator
enumerationAsScalaIteratorEnumerationIterator
asScalaBufferListmutable.Buffer
asScalaSetSetmutable.Set
mapAsScalaMapMapmutable.Map
dictionaryAsScalaMapDictionarymutable.Map
propertiesAsScalaMapPropertiesmutable.Map
asScalaConcurrentMapconcurrent.ConcurrentMapmutable.ConcurrentMap

并行集合

Scala提供的用于操纵大型集合的解决方案十分诱人。这些任务通常可以很自然地并行操作。举例来说,要计算所有元素之和,多个线程可以并发地计算不同分区的和;最后这些部分的结果被汇总到一起。要对这样的并发任务进行排程是很伤脑筋的,但若用Scala ,则你无须担心这个问题。如果coll是个大型集合,那么

val coll = List(1, 2, 3, 4, 5, 6, 7, 8, 9)
println(coll.par.sum)

上述代码会并发地对它求和。par方法产出当前集合的一个并行实现。该实现会尽可能并行地执行集合方法。例如:

coll.par.count(_ % 2 == 0)

将会并行地对偶集合求前提表达式的值,然后将结果组合在一起,得出coll中所有偶数的数量。
你可以通过对要遍历的集合应用.par并行化for循环,就像这样:

for (i <- ((0 until 10)).par) {
      print(s"$i ")
    }
// 输出: 7 9 3 2 1 8 5 4 0 6

数字是按照作用于该任务的线程产出的顺序输出的。而在for/yield循环中,结果是依次组装的。如下:

(for(i<- (0 until 100000).par) yield i) == (0 until 100000)

注意:如果并行运算修改了共享的变量,则结果无法预知。举例来说, 不要更新个共享的计数器:

    var count = 0
    for (c <- coll.par) {
      if (c % 2 == 0) {
        count += 1
      }
    }

par方法返回的并行集合属于扩展自ParSeq、ParSet或ParMap特质的类型。这些并不是Seq、Set、Map 的子类型,你不能向一个预期顺序集合( sequential collection ) 的方法传入并行集合。
你可以用seq方法将并行集合转换回顺序集合:

val result= coll.par.filter(_ % 2 == 0).seq

并非所有方法都能被并行化。例如,reduceLeft和reduceRight要求每个操作符都要按顺序应用。有另一个方法reduce,对集合的部分进行操作然后组合出结果。为了让这个方案可行,操作符必须是结合的( associative ),它必须满足 ( a   o p   b )   o p   c = a   o p   ( b   o p   c ) (a\ op\ b)\ op\ c = a\ op\ (b\ op\ c) (a op b) op c=a op (b op c)的要求。例如,加法是结合的而减法不是: ( a − b ) − c ≠ a − ( b − c ) (a - b) - c \neq a - (b - c) (ab)c=a(bc)
同理,还有一个fold方法对集合的部分进行操作。可惜它并不像foldLeft和foldRight那么灵活,操作符的两个参数都必须是元素。也就是说,你可以执行coll.par.fold(0)(_ + _),但不能执行更复杂的折叠。
要解决这个问题,有个更一般的aggregate方法,将操作符应用到集合的部分,然后用另一个操作符来组合出结果。例如,str.par.aggregate(Set[Char]())(_ + _, _ ++ _)等效于str.foldLeft(Set[Char]())(_ + _),得到str中所有不同字符的集。
说明: 默认情况下,并行集合使用全局的fork-join线程池,该线程池非常适用于高处理器开销的计算。如果你执行的并行步骤包含阻塞调用,就应该另选一种“执行上下文(execution context)”。

参考:快学scala(第二版)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值