python中线程安全的数据结构_Scala(八)-①-数据结构-集合操作-线程安全的集合-操作符重载...
① 集合操作
Why
为什么需要集合操作?集合操作都包括哪些?Scala的集合操作主要为了适应大数据的发展,我们以Map为例.于事需入局,于程需入题,先看下题.
入题
请将list(3,5,7) 中的所有元素都 * 2,将其结果放到一个新的集合中返回,即返回一个新的list(6,10,14), 请编写程序实现.
传统解决方案
object InQuestion {
def main(args: Array[String]): Unit = {
val list1 = List(3, 5, 7)
var list2 = List[Int]()
for (item
list2 = list2 :+ item * 2
}
println(list2)
}
}
优点:
处理直接
缺点:
不够简洁
没有提现出函数式编程
不利于复杂的数据处理业务
map映射操作解决方案
分析
其实就是一个关于集合元素映射操作的问题
在Scala中可以通过map映射操作来解决:将集合中的每一个元素通过指定功能(函数)映射(转换)成新的结果集合.这里其实就是所谓的将函数作为参数传递给另外一个函数,这是函数式编程的特点.
HashMap的API为例
def map[B](f: (A) ⇒ B): HashSet[B]
[B]是泛型
map是一个高阶函数,可以接收函数f:(A)=>B
HashSet[B]就是返回的新的集合
代码
将函数作为变量进行传递,其会在map函数内部再对f1进行调用,一般都会对每一个元素调用一次.
def testCaseForMap(): Unit = {
println("=============map=============")
val list1 = List(3, 5, 7)
def f1(n1: Int): Int = {
2 * n1
}
val list2 = list1.map(f1)
println(list2)
}
How
相关的函数
语法和规则
扁平化映射-flatmap函数
flat即压扁,压平,扁平化,效果就是将集合中的每个元素的子元素映射到某个函数并返回新的集合.
object CollectionOpDemo01ForFlatMap {
def main(args: Array[String]): Unit = {
val names = List("Alice", "Bob", "Nick")
def upper( s : String ) : String = {
s. toUpperCase
}
println(names.flatMap(upper))
}
}
过滤-filter函数
将符合要求的数据(筛选)放置到新的集合中
object CollectionOpDemo02FoFilter {
def main(args: Array[String]): Unit = {
val names = List("Alice", "Bob", "Nick")
def startA(s:String): Boolean = {
s.startsWith("A")
}
val names2 = names.filter(startA)
println("names=" + names2)
}
}
化简(聚合)-reducerLeft
对集合依据函数进行聚合运算,reducerLeft中的函数式二元函数.
object CollectionOpDemo03ForReducerLeft {
def main(args: Array[String]): Unit = {
val list = List(1, 20, 30, 4, 5)
def sum(n1: Int, n2: Int): Int = {
n1 + n2
}
val res = list.reduceLeft(sum)
println("res=" + res)
}
}
练习
使用化简的方法求出 List(3,4,2,7,5) 最小的值
def testCaseForWork01(): Unit = {
val list = List(1, 2, 3, 4 ,5)
def minus( num1 : Int, num2 : Int ): Int = {
num1 - num2
}
println(list.reduceLeft(minus)) // 输出? -13 // ((((1-2)-3)-4)-5) = 1-(2+3+4+5)
println(list.reduceRight(minus)) //输出? 3 // (1-(2-(3-(4-5)))) =
}
def testCaseForWork02(): Unit = {
var l = List(3,4,2,7,5)
def max(num1: Int,num2: Int):Int = {
if (num1 > num2) num1 else num2
}
def min(num1: Int,num2: Int):Int = {
if (num1 < num2) num1 else num2
}
println(l.reduceLeft(max))
println(l.reduceLeft(min))
}
折叠-fold
fold函数将上一步返回的值作为函数的第一个参数继续传递参与运算,直到list中的所有元素被遍历.
可以把reduceLeft看做简化版的foldLeft.
override /*TraversableLike*/
def reduceLeft[B >: A](f: (B, A) => B): B =
if (isEmpty) throw new UnsupportedOperationException("empty.reduceLeft")
else tail.foldLeft[B](head)(f)
代码
object CollectionOpDemo04ForFold {
def main(args: Array[String]): Unit = {
// 折叠
val list = List(1, 2, 3, 4)
def minus( num1 : Int, num2 : Int ): Int = {
num1 - num2
}
println(list.foldLeft(5)(minus)) // 相当于list(5, 1, 2, 3, 4) list.reduceLeft(minus)
println(list.foldRight(5)(minus)) // 相当于list(1, 2, 3, 4, 5) list.reduceLeft(minus)
}
}
foldLeft和foldRight 缩写方法分别是:/:和:\
def testCaseForWork01(): Unit = {
println("testCaseForWork01")
val list4 = List(1, 9, 2, 8)
def minus(num1: Int, num2: Int): Int = {
num1 - num2
}
var i6 = (1 /: list4) (minus) // ==> list4.foldLeft(0)(minus) 1-20
println(i6)
i6 = (100 /: list4) (minus) // 100 - 20
println(i6)
i6 = (list4 :\ 10) (minus) // list4.foldRight(10)(minus) // -4
println(i6)
}
扫描-scanLeft-scanRight
扫描,即对某个集合的所有元素做fold操作,但是会把产生的所有中间结果放置于一个集合中保存并返回
object CollectionOpDemo05ForScan {
def main(args: Array[String]): Unit = {
def minus( num1 : Int, num2 : Int ) : Int = {
num1 - num2
}
// scanLeft 计算每次折叠结果,第一次直接保存
//5 (1,2,3,4,5) =>(5,4,2,-1,-5,-10)
val i8 = (1 to 5).scanLeft(5)(minus) //IndexedSeq[Int]
println(i8)
def add( num1 : Int, num2 : Int ) : Int = {
num1 + num2
}
//5 (1,2,3,4,5) =>(5,6,8, 11,15,20)
// (1,2,3,4,5),5 => (20,19,17,14,10,5)
val i9 = (1 to 5).scanRight(5)(add) //IndexedSeq[Int]
println(i9)
}
}
拉链-zip
当我们需要将两个集合进行 对偶元组合并,可以使用拉链
image.png
val list1 = List(1, 2 ,3)
val list2 = List(4, 5, 6)
val list3 = list1.zip(list2)
println("list3=" + list3)
拉链的本质就是两个集合的合并操作,合并后每个元素是一个 对偶元组
集合不限于List, 也可以是其它集合比如 Array
迭代器
所有的集合都有迭代器,可以用迭代器来进行遍历.
使用迭代器遍历
object CollectionOpDemo06ForIterator{
def main(args: Array[String]): Unit = {
val iterator = List(1, 2, 3, 4, 5).iterator //
println("--------遍历方式1 -----------------")
while (iterator.hasNext) {
println(iterator.next())
}
println("--------遍历方式2 for -----------------")
for(enum
println(enum) //
}
}
}
原理
iterator的构建实际是AbstractIterator的一个匿名子类,该子类提供了hasNext next等方法
override /*IterableLike*/
def iterator: Iterator[A] = new AbstractIterator[A] {
var these = self
def hasNext: Boolean = !these.isEmpty
def next(): A =
if (hasNext) {
val result = these.head; these = these.tail; result
} else Iterator.empty.next()
流-stream
一句话:流是一个集合,用于存放无穷多个元素.末尾元素遵守lazy规则,即要使用才会进行计算.
使用tail会自动计算生成新的数据
使用head获取头元素
不能使用last,会导致程序无限循环
object CollectionOpDemo07ForStream {
def testCaseForStream01(): Unit = {
//创建Stream
def numsForm(n: BigInt) : Stream[BigInt] = n #:: numsForm(n + 1)
def multi(x:BigInt) : BigInt = {
x * x
}
println(numsForm(5).map(multi)) //?
}
def testCaseForQuicklyStart() = {
//创建Stream
def numsForm(n: BigInt) : Stream[BigInt] = n #:: numsForm(n + 1)
val stream1 = numsForm(1)
println(stream1) //
//取出第一个元素
println("head=" + stream1.head) //
println(stream1.tail) //
println(stream1) //?
}
def main(args: Array[String]): Unit = {
testCaseForQuicklyStart()
testCaseForStream01()
}
}
视图-view
对其他集合应用view方法来得到类似Stream的懒加载特性效果.这在python中叫做generator.
view主要用在当要生成大量数据的时候,如果一次性生成会占用大量内存.
object CollectionOpDemo08ForView {
def main(args: Array[String]): Unit = {
def eq(i: Int): Boolean = {
i.toString.equals(i.toString.reverse)
}
//1.没有使用view
val viewSquares1 = (1 to 100).filter(eq)
println(viewSquares1)
// 2.使用view来迭代生成大量数据
val viewSquares2 = (1 to 100)
.view
.filter(eq)
for (item
println(item)
}
println(viewSquares2)
}
}
② 线程安全的集合
所有线程安全的集合都是以Synchronized开头的集合
SynchronizedBuffer
SynchronizedMap
SynchronizedPriorityQueue
SynchronizedQueue
SynchronizedSet
SynchronizedStack
Why
Scala提供了针对可变集合的线程安全集合.
Scala为了充分使用多核CPU,提供了并行集合(有别于前面的串行集合),用于多核环境的并行计算
How
parallel并行DEMO
打印1~5
代码
val maxNumber = 1000000
// 单核心,输出有序
var startTime = System.currentTimeMillis()
(1 to maxNumber).foreach(println(_))
var endTime = System.currentTimeMillis()
val t1 = (endTime-startTime)/1000
println(s"单核计算花费了${t1}秒")
println()
// 多核计算,输出无序
startTime = System.currentTimeMillis()
(1 to maxNumber).par.foreach(println(_))
endTime = System.currentTimeMillis()
val t2 = (endTime-startTime)/100
println(s"单核计算花费了${t2}秒,快了${t2/t1}倍")
输出
查看并行集合中元素访问的线程
val result1 = (0 to 100).map{case _ => Thread.currentThread.getName}
val result2 = (0 to 100).par.map{case _ => Thread.currentThread.getName}
println(result1)
println(result2)
What
Divide and conquer分治算法
Scala通过splitters,combiners等抽象层来实现,主要原理是将计算工作分解很多任务,分发给一些处理器去完成,并将它们处理结果合并返回
Work stealin算法
主要用于任务调度负载均衡(load-balancing),通俗点完成自己的所有任务之后,发现其他人还有活没干完,主动(或被安排)帮他人一起干,å这样达到尽早干完的目的
③ 操作符重载
Scala中重载了大量操作符,并且准许程序员自定义重载操作符.
Why
方便使用操作符对进行计算
How
一元操作符-后置操作符: AOp 等同于 A.操作符, 如果操作符定义的时候不带()则调用时不能加括号
一元操作符-前置操作符: +、-、!、~等操作符A等同于A.unary_操作符
二元操作符~中置操作符: A Op B 等同于 A.op(B)
二元操作符-赋值操作符:A op= B 等同于 A = A op B. 比如 A += B 等价 A = A + B
object CollectionOpDemo10ForOpOverload{
def main(args: Array[String]): Unit = {
val money = new Money(100)
money + 1
money += 1
money++;
!money
println(money.money)
}
}
class Money(n : Int) {
var money : Int = n
// 二元-中置操作符
def +(n: Int):Money = {
this.money += n
this
}
// 二元赋值操作符
def +=(n: Int):Money = {
this.money += n
this
}
// 一元操作符 ++
def ++():Money = {
this.money += 1
this
}
// 一元操作符 !
def unary_!():Money = {
this.money = -this.money
this
}
}
python中线程安全的数据结构_Scala(八)-①-数据结构-集合操作-线程安全的集合-操作符重载...相关推荐
- 使用 Python 中的漂亮打印美化您的数据结构
处理数据对于任何 Pythonista 都是必不可少的,但有时这些数据并不是很漂亮.计算机不关心格式,但如果没有好的格式,人类可能会发现一些难以阅读的东西.当您print()在大型字典或长列表上使用时 ...
- COJ 1008 WZJ的数据结构(八) 树上操作
传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=986 WZJ的数据结构(八) 难度级别:E: 运行时间限制:3000ms: ...
- python 中文件输入输出及os模块对文件系统的操作
整理了一下python 中文件的输入输出及主要介绍一些os模块中对文件系统的操作. 文件输入输出 1.内建函数open(file_name,文件打开模式,通用换行符支持),打开文件返回文件对象. 2. ...
- linux用户读取文件过程,Python中读取写入文件并进行文件与用户交互的操作
一.提前知识点 在Python中是同样和其他语言一样可以进行文件的读取写入操作,值得注意的是,Python中打开文件读取的方式有几种,分别是以下几种: f = open('username.txt') ...
- Python中取余、除法、取整的操作逻辑
对于python而言,容易混淆的运算符有 除(/),取余(%),取整(//). 取余(%) 对于这三种运算符而言,取余操作有时会令人费解.例如: 7 % 3 =11 % 10 = 10.3 % 10 ...
- python中如何取余_python如何实现取余操作的方法
python如何实现取余操作的方法 发布时间:2020-08-17 09:36:53 来源:亿速云 阅读:68 作者:小新 这篇文章主要介绍python如何实现取余操作的方法,文中介绍的非常详细,具有 ...
- python中documentelement_python网络编程学习笔记(八):XML生成与解析(DOM、ElementTree)...
xml.dom篇 DOM是Document Object Model的简称,XML 文档的高级树型表示.该模型并非只针对 Python,而是一种普通XML 模型.Python 的 DOM 包是基于 S ...
- python中判断无向图是否有环_数据结构与算法:17 图
17 图 知识结构: 图1 知识结构 1. 图的基本概念与术语 1.1 图的定义 图由顶点集和边集组成,记为 . 顶点集:顶点的有穷非空集合,记为. 边集:顶点偶对的有穷集合,记为 . 边: 无向边: ...
- python中f点flush是什么函数_Python文件操作及内置函数flush原理解析
1.打开文件得到文件句柄并赋值给一个变量 2.通过句柄对文件进行操作 3.关闭文件 示例文件 '你好呀' 我是于超 嗯 再见 文件操作基本流程 f=open('chenli',encoding='ut ...
最新文章
- 安装tensorflow-gpu==1.13.1成功案例
- Fescar 发布 0.3.0 版本, 支持 Eureka 注册中心
- [转]Loadrunner Error code 10053 Tomcat 连接器(connector)优化
- PHP CGI 中 fix_pathinfo 引起的安全隐患
- UA MATH567 高维统计II 随机向量6 亚高斯随机向量的应用: 半正定规划
- 桌面虚拟化之运维支持
- 程序员面试金典适合java么,【程序员面试金典】面试题 01.03. URL化(示例代码)
- sqlserver 导出mysql,sqlserver数据(表)导出到mysql
- 网站底部添加访客阅读次数总访问量在线人数代码
- 前端每日实战:33# 视频演示如何用纯 CSS 创作牛奶文字变换效果
- Linux基础——014_钩子程序同步代码
- 【开源之美】nanomsg(2) :req/rep 模式
- matlab简单几何图形的识别代码,MATLAB识别几何图形
- 独孤求败-小滴云架构大课十八式【xiaoecf】
- 计算机里的文案怎么设置背景,如何将图片设置为Word文档的背景
- 云上发展,唯快不破!IT部门是数字化转型的变革者 | 凌云时刻
- 国内外好的OKR管理工具有哪些
- 软件著作权的鉴定材料提交
- vue+elemenUI项目,仿照京东商城,完成电商网站的订单中心
- 楚留香服务器维护,楚留香手游3月9日维护更新公告