IDEA Git操作(三)使用 cherry-pick、交互式 rebase 自由修改提交树
說(shuō)明
本教程按照?git在線(xiàn)練習(xí)?順序進(jìn)行,將在線(xiàn)測(cè)試的命令操作落地到 IDEA,使用開(kāi)發(fā)工具來(lái)實(shí)現(xiàn)所有在線(xiàn)練習(xí)中的操作。
你可以結(jié)合?git在線(xiàn)練習(xí)?來(lái)學(xué)習(xí)本教程,先在線(xiàn)學(xué)習(xí)git命令,再在 IDEA 中實(shí)現(xiàn)相同操作。
?
cherry-pick
?
準(zhǔn)備提交結(jié)構(gòu)
?
- 切換到 master,并重置到第二次提交
- 刪除 pushed 和 local 分支
新建 bugFix、side 和 another 分支
- 對(duì)bugFix、side和another分支,分別做兩次提交
- 切換到 master
上面的提交歷史對(duì)照?learngitbranching.js.org?的結(jié)構(gòu)圖
cherry-pick bufFix 2、side 1和another 2三個(gè)提交到 master 分支
選中這三個(gè)提交
右鍵選擇 cherry-pick
如果出現(xiàn)代碼合并提示,選擇 merge,將 bufFix 2 提交的代碼合并到 master 的代碼
按照正確代碼邏輯,向中間合并代碼
完成后,生成了一個(gè)新的提交
接下來(lái),按照相同的操作,完成 side 1 和 another 2 的代碼合并操作,同樣也會(huì)生成兩個(gè)新的提交
上面的提交歷史對(duì)照?learngitbranching.js.org?的結(jié)構(gòu)圖
交互式 rebase
?
準(zhǔn)備提交結(jié)構(gòu)
?
- 重置master到第二次提交
- 刪除 bugFix、side 和 another 分支
- 做四次提交
上面的提交歷史對(duì)照?learngitbranching.js.org?的結(jié)構(gòu)圖
用交互式 rebase 操作自由調(diào)整提交
在 master 分支,右鍵點(diǎn)擊 “添加打印3”,選擇交互式 rebase
在交互界面中,丟棄“添加打印3”
向上移動(dòng)一步 “添加打印6”
查看將要執(zhí)行的命令
在這里看到,會(huì)按以下順序執(zhí)行:
點(diǎn)擊開(kāi)始執(zhí)行 rebase 操作
?
過(guò)程中可能會(huì)出現(xiàn)3次合并代碼的操作提示,可以按照三步的順序,合并三句打印代碼
上面的提交歷史對(duì)照?learngitbranching.js.org?的結(jié)構(gòu)圖
用交互 rebase 將 4,6,5 壓縮成一個(gè)分支
learngitbranching.js.org?中略過(guò)了壓縮分支的操作
右鍵點(diǎn)擊“添加打印4”的提交,執(zhí)行交互式 rebase
將 5 和 6 設(shè)置為 Fixup
設(shè)置完的狀態(tài)如下
rebase 完成后,三次提交被壓縮為一次提交
筆記匯總目錄
Spring Cloud 微服務(wù)
Spring Cloud入門(mén)操作手冊(cè)(Hoxton)
?
RabbitMQ
RabbitMQ
RabbitMQ - Spring boot 整合
Lucene Solr
Lucene Solr 811
?
Docker
Docker
Docker案例
?
Kubernetes
Kubernetes
k8s部署Spring Cloud應(yīng)用
?
分布式事務(wù)
分布式事務(wù)(一)Mysql本地事務(wù)和事務(wù)隔離級(jí)別
分布式事務(wù)(二)分布式事務(wù)方案
分布式事務(wù)(三)Seata分布式事務(wù)框架-AT模式介紹
分布式事務(wù)(四)Seata AT模式-Spring Cloud微服務(wù)案例
分布式事務(wù)(五)Seata AT模式-Spring Cloud微服務(wù)添加 AT 分布式事務(wù)
分布式事務(wù)(六)Seata TCC模式-TCC模式介紹
分布式事務(wù)(七)Seata TCC模式-Spring Cloud微服務(wù)添加 TCC 分布式事務(wù)
分布式事務(wù)(八)Spring Cloud微服務(wù)系統(tǒng)基于Rocketmq可靠消息最終一致性實(shí)現(xiàn)分布式事務(wù)
?
RocketMQ
RocketMQ (一) 安裝
RocketMQ (二) 雙主雙從同步復(fù)制集群方案
RocketMQ (三) 基本原理
RocketMQ (四) 使用RocketMQ原生API收發(fā)消息代碼樣例
RocketMQ (五) Springboot 整合 RocketMQ 收發(fā)消息樣例
RocketMQ 發(fā)送事務(wù)消息原理分析和代碼實(shí)現(xiàn)
Java基礎(chǔ)
java編程基礎(chǔ)(一)二進(jìn)制
java編程基礎(chǔ)(二)位運(yùn)算符
java編程基礎(chǔ)(三)冒泡排序
java編程基礎(chǔ)(四)選擇排序
java編程基礎(chǔ)(五)二分法查找
java編程基礎(chǔ)(六)遞歸
2006
就業(yè)
簡(jiǎn)歷:自我介紹: 接收短期或長(zhǎng)期出差, 接收高強(qiáng)度加班抗壓能力極強(qiáng)
項(xiàng)目:
自研項(xiàng)目: 主題一致,
外包:
人力:類(lèi)型一致
項(xiàng)目:類(lèi)型一致
國(guó)企:
復(fù)習(xí)
1.做題,打樁: Java面試寶典,碼出高效
2.mysql(多表聯(lián)查)\servlet()SSM(圖)
3.SSM(圖) shiro
4.jt業(yè)務(wù) redis ( 是什么, 在項(xiàng)目里解決什么問(wèn)題, ) \Nginx\Mycat\SSO\zookeeper\dubbo
5.cloud mq 分布式事務(wù)
課程安排
大數(shù)據(jù)
指海量數(shù)據(jù)及其處理方式
大數(shù)據(jù)(big data),IT行業(yè)術(shù)語(yǔ),是指無(wú)法在一定時(shí)間范圍內(nèi)用常規(guī)軟件工具進(jìn)行捕捉、管理和處理的數(shù)據(jù)集合,是需要新處理模式才能具有更強(qiáng)的決策力、洞察發(fā)現(xiàn)力和流程優(yōu)化能力的海量、高增長(zhǎng)率和多樣化的信息資產(chǎn)。
在維克托·邁爾-舍恩伯格及肯尼斯·庫(kù)克耶編寫(xiě)的《大數(shù)據(jù)時(shí)代》 [1] 中大數(shù)據(jù)指不用隨機(jī)分析法(抽樣調(diào)查)這樣捷徑,而采用所有數(shù)據(jù)進(jìn)行分析處理。大數(shù)據(jù)的5V特點(diǎn)(IBM提出):Volume(大量)、Velocity(高速)、Variety(多樣)、Value(低價(jià)值密度)、Veracity(真實(shí)性)。
大數(shù)據(jù)相關(guān)技術(shù)
數(shù)據(jù)收集
爬蟲(chóng),python,jsoup,Nucth
數(shù)據(jù)倉(cāng)庫(kù) :Hive?ELK
日志:Flume分布式日志收集工具,log4j
IOT:物聯(lián)網(wǎng)
數(shù)據(jù)清洗
SQL: id name age gender addr 姓名 性別 18歲及以上的 select name, gender from user where age >= 18
邏輯: if(person != null){…}
數(shù)據(jù)存儲(chǔ)
Hadoop.HDFS?(Google File System)
數(shù)據(jù)處理
離線(xiàn)處理: Hive
流式處理:?Flink,Spark,Storm
MQ:?kafka
數(shù)據(jù)傳輸:?Sqoop
狀態(tài)監(jiān)控:zookeeper
環(huán)境準(zhǔn)備
8G 克隆三臺(tái)虛擬機(jī)
hadoop01 1G
hadoop02 512M
hadoop03 512M
4G 克隆一臺(tái)虛擬機(jī)
hadoop01 1G
hadoop
分布式的海量數(shù)據(jù)存儲(chǔ)和處理系統(tǒng),同時(shí)具有集群資源管理和任務(wù)調(diào)度的能力.
歷史
Google:全文檢索,海量數(shù)據(jù)存儲(chǔ),海量數(shù)據(jù)處理,爬蟲(chóng)
2004年《google file system》(GFS)《Mapreduce》(MR)
2006年《Big Table》(上億行,上百萬(wàn)列這樣的高表或者寬表)
Doug cutting(Java): Nutch(爬蟲(chóng)) Lucene、HDFS、Mapreduce Hadoop
Hbase(k,v)
大數(shù)據(jù)技術(shù)發(fā)源自搜索引擎領(lǐng)域,直到現(xiàn)在很多大數(shù)據(jù)技術(shù)中都會(huì)有搜索引擎的影響.
DataSet: 離線(xiàn)數(shù)據(jù)
DataStream: 流式數(shù)據(jù)
概念
Hadoop允許使用簡(jiǎn)單的編程模型跨計(jì)算機(jī)集群對(duì)大型數(shù)據(jù)集進(jìn)行分布式處理
版本
hadoop1.x: HDFS(海量數(shù)據(jù)存儲(chǔ)) Mapreduce(海量數(shù)據(jù)的離線(xiàn)計(jì)算,集群資源管理,任務(wù)調(diào)度)
hadoop2.x: HDFS(海量數(shù)據(jù)存儲(chǔ)) Mapreduce(海量數(shù)據(jù)的離線(xiàn)計(jì)算) Yarn(集群資源管理,任務(wù)調(diào)度) 2.7.1
hadoop3.x: HDFS(海量數(shù)據(jù)存儲(chǔ)) Mapreduce(海量數(shù)據(jù)的離線(xiàn)計(jì)算) Yarn(集群資源管理,任務(wù)調(diào)度)
HDFS
海量數(shù)據(jù)存儲(chǔ),無(wú)限存儲(chǔ)
Hadoop的安裝
可能出現(xiàn)的錯(cuò)誤
提示命令找不到 環(huán)境變量配置錯(cuò)誤或者沒(méi)有source /etc/profile
Flume
定義
是一個(gè)分布式的海量日志收集工具.用于收集,聚合,移動(dòng)大量的日志數(shù)據(jù). 具備簡(jiǎn)單的流式數(shù)據(jù)處理模型的特點(diǎn).但是不需要計(jì)算.所以說(shuō)他簡(jiǎn)單.
重要概念 RegExp
log : 江哥今天沒(méi)來(lái)上課,不知道去哪了
Event:事件,JSON = {“headers” : “value”, “body” : “江哥今天沒(méi)來(lái)上課,不知道去哪了”},Flume在接收到日志數(shù)據(jù)之后,會(huì)先將其進(jìn)行封裝,每一條日志都會(huì)被封裝為一個(gè)Event.然后再進(jìn)行傳輸.
Agent: 代理, flume是一個(gè)分布式的軟件,就像Hadoop中不同的節(jié)點(diǎn)都有自己的名字一樣.flume的所有節(jié)點(diǎn)都叫Agent,每一個(gè)Agent中都包含三個(gè)部分.sourcechannel和sink
Source: 數(shù)據(jù)源,是Flume用來(lái)接收數(shù)據(jù)的組件.日志數(shù)據(jù)首先會(huì)進(jìn)入到source模塊,并在改模塊進(jìn)行封裝(Event).輸出給Channel進(jìn)行緩存.
Channel:緩存,被動(dòng)接收source傳來(lái)的Event并進(jìn)行緩存.等待Sink對(duì)event的消費(fèi).一般情況下,為了追求速度,都使用內(nèi)存資源來(lái)緩存數(shù)據(jù),那么此時(shí)就要注意:需要給緩存設(shè)置最大值.
Sink:輸出, 指定數(shù)據(jù)輸出的位置,消費(fèi)Channel中的event
靈活的特性
多級(jí)流動(dòng)
扇入
扇出
知識(shí)回顧
Flume是一個(gè)分布式的日志收集工具.
重要概念
Event:事件,Flume在收集到日志數(shù)據(jù)之后不是直接傳輸,而是先封裝其為
Event(JSON) : {“headers”:“自定義內(nèi)容”,“body”:“日志本身”}
Agent:Flume本身是分布式的,他所有的節(jié)點(diǎn)都叫做Agent,代理. 其中每個(gè)agent內(nèi)部都會(huì)有三個(gè)組件,分別是,source\channel\sink
Source:Flume的數(shù)據(jù)源,負(fù)責(zé)數(shù)據(jù)的接入,當(dāng)日志數(shù)據(jù)進(jìn)入到source時(shí),source會(huì)先將其進(jìn)行封裝(Event),然后將event輸出到Channel中進(jìn)行緩存.
Channel: 被動(dòng)接收source傳來(lái)的數(shù)據(jù),對(duì)所有數(shù)據(jù)進(jìn)行緩存,等待Sink的消費(fèi).一般情況為了追求速度,使用內(nèi)存來(lái)做緩存,所以必須設(shè)置最大容量.
Sink:指定數(shù)據(jù)的輸出位置,消費(fèi)Channel中緩存的數(shù)據(jù).
靈活特性
多級(jí)流動(dòng): 兩臺(tái)以上的服務(wù)器串聯(lián)傳輸數(shù)據(jù).
扇入: 多個(gè)服務(wù)器同時(shí)將數(shù)據(jù)發(fā)送給一臺(tái)服務(wù)器
扇出: 一臺(tái)服務(wù)器講數(shù)據(jù)分發(fā)給多臺(tái)
Hive
MapReduce在離線(xiàn)數(shù)據(jù)處理中遇到的問(wèn)題
概念
Hive是一個(gè)基于Hadoop的數(shù)據(jù)倉(cāng)庫(kù)客戶(hù)端. 使用簡(jiǎn)單的SQL方式來(lái)處理海量離線(xiàn)數(shù)據(jù),避免開(kāi)發(fā)MR程序的成本過(guò)高的問(wèn)題.內(nèi)部集成了非常豐富的函數(shù)庫(kù).并且在內(nèi)置函數(shù)不能滿(mǎn)足開(kāi)發(fā)需求時(shí).Hive也允許用戶(hù)自定義函數(shù)(UDF)來(lái)解決更為復(fù)雜的問(wèn)題(很少)
數(shù)據(jù)倉(cāng)庫(kù)
倉(cāng)庫(kù)(有用,但不常用的)
數(shù)據(jù)倉(cāng)庫(kù)是一個(gè)面向主題的,穩(wěn)定的,集成的,反映歷史數(shù)據(jù)的數(shù)據(jù)存儲(chǔ)系統(tǒng).一般用于為管理者的決策分析提供數(shù)據(jù)的支持.
Hive表的類(lèi)型
內(nèi)部表和外部表
MANAGED_TABLE 內(nèi)部表(托管表): 先創(chuàng)建表,然后在表中寫(xiě)數(shù)據(jù),內(nèi)部表指的是數(shù)據(jù)和表結(jié)構(gòu)都屬于Hive當(dāng)Hive要?jiǎng)h除這個(gè)表時(shí),元數(shù)據(jù)和表數(shù)據(jù)都會(huì)被刪除.
create table tb_book1 (id int, name string) row format delimited fields terminated by ‘\t’;
EXTERNAL_TABLE 外部表: 先有數(shù)據(jù)已經(jīng)保存在HDFS中,根據(jù)數(shù)據(jù)文件的格式,創(chuàng)建Hive的表結(jié)構(gòu),然后將表結(jié)構(gòu)映射在數(shù)據(jù)上,來(lái)管理相關(guān)數(shù)據(jù).
create external table tb_book2 (id int,name string) row format delimited fields terminated by ‘\t’ location ‘/2006book2’;
實(shí)驗(yàn)
分區(qū)表
分區(qū)表時(shí)Hive作為數(shù)據(jù)倉(cāng)庫(kù)實(shí)現(xiàn)面向主題的唯一方式
分桶表
分桶的應(yīng)用場(chǎng)景: 1.HashMap 2.數(shù)據(jù)庫(kù)分庫(kù) 3.Nginx負(fù)載均衡 IPhash
只在測(cè)試時(shí).數(shù)據(jù)量大并且隨意抽取樣本數(shù)據(jù)不準(zhǔn)確時(shí).使用分桶表.
知識(shí)回顧
Hive是什么? 是一個(gè)基于Hadoop的數(shù)據(jù)倉(cāng)庫(kù)客戶(hù)端,使用SQL的方式操作.內(nèi)置了非常豐富的函數(shù)庫(kù).并且支持自定義函數(shù).
數(shù)據(jù)倉(cāng)庫(kù)? 一個(gè)面向主題的,穩(wěn)定的,集成的,反應(yīng)歷史數(shù)據(jù)的數(shù)據(jù)存儲(chǔ)系統(tǒng),一般為管理者提供決策分析的數(shù)據(jù)支持.
內(nèi)部表: 先創(chuàng)建表然后在表中寫(xiě)數(shù)據(jù)
外部表托管表:先有數(shù)據(jù),然后根據(jù)數(shù)據(jù)文件的格式,創(chuàng)建表結(jié)構(gòu),然后將表結(jié)構(gòu)映射在數(shù)據(jù)上
內(nèi)部表刪除數(shù)據(jù)時(shí),元數(shù)據(jù)和表數(shù)據(jù)都會(huì)被刪除,外部表刪除時(shí),元數(shù)據(jù)會(huì)被刪除,表數(shù)據(jù)則不會(huì)被刪除
分區(qū)表:Hive作為數(shù)據(jù)倉(cāng)庫(kù)實(shí)現(xiàn)面向主題的唯一方式.
分桶表:只在測(cè)試階段使用,為了解決,數(shù)量大,并且數(shù)據(jù)依據(jù)時(shí)間或者類(lèi)似其他維度有規(guī)律.測(cè)試時(shí)如果全量原始數(shù)據(jù)加載測(cè)試,耗時(shí)太長(zhǎng),如果隨意抽取部分?jǐn)?shù)據(jù)結(jié)果不具有代表性,可能會(huì)影響判斷. 此時(shí),使用分桶表來(lái)解決這個(gè)數(shù)據(jù)抽樣問(wèn)題
項(xiàng)目第二次重構(gòu): 海量日志數(shù)據(jù)的離線(xiàn)分析
Sqoop
是連接基于HDFS的文件存儲(chǔ)系統(tǒng),和關(guān)系型數(shù)據(jù)庫(kù)的數(shù)據(jù)橋梁.能夠輕松實(shí)現(xiàn)將HDFS中存儲(chǔ)的數(shù)據(jù)輸出到Mysql等關(guān)系型數(shù)據(jù),或者從關(guān)系型數(shù)據(jù)庫(kù)中導(dǎo)入數(shù)據(jù)到HDFS.
Kafka
MQ,消息隊(duì)列, 海量數(shù)據(jù)存儲(chǔ)(HDFS),和流式數(shù)據(jù)處理(Spark,Flink)
ActiveMQ(6k)\RabbitMQ(1.2w)\RocketMQ(3-5w):更適合于業(yè)務(wù)系統(tǒng),能夠保證數(shù)據(jù)一致性(數(shù)據(jù)不會(huì)丟失)
Kafka(25-50w)\ZeroMQ(Storm)速度非常快,但是有小概率的數(shù)據(jù)丟失情況(十億分之一)
重要概念
消費(fèi)者\(yùn)生產(chǎn)者客戶(hù)端: 連接消費(fèi)者和生產(chǎn)者,達(dá)到解耦的目的.同時(shí)保證Kafka的可伸縮性.
Broker: kafka中,所有的機(jī)器節(jié)點(diǎn)都叫做broker按照int類(lèi)型數(shù)據(jù)進(jìn)行編號(hào)默認(rèn)從0開(kāi)始.主要的任務(wù)就是保存隊(duì)列中的數(shù)據(jù).
Topic: 將不同業(yè)務(wù)的數(shù)據(jù),用主題(文件夾)隔離開(kāi),避免數(shù)據(jù)錯(cuò)誤消費(fèi).一個(gè)主題上可以?huà)煸诙鄠€(gè)生產(chǎn)者和多個(gè)消費(fèi)者.
Partition: 按照0-n來(lái)編號(hào),實(shí)際上就是在不同的Broker中來(lái)分布存放Topic的一部分?jǐn)?shù)據(jù),具有不同事件鍵的數(shù)據(jù)會(huì)被分配到不同的分區(qū)中,來(lái)隔離不同子業(yè)務(wù)的數(shù)據(jù).在分區(qū)內(nèi)部,所有數(shù)據(jù)都會(huì)被進(jìn)行編號(hào)0-n 來(lái)保證數(shù)據(jù)消費(fèi)的順序是FIFO.并且與Offset配合來(lái)使消費(fèi)者避免重復(fù)消費(fèi)的問(wèn)題,或者消費(fèi)指定的數(shù)據(jù).
Leader\Follower: kafka為了保障數(shù)據(jù)的安全.在分區(qū)層面上對(duì)數(shù)據(jù)進(jìn)行了備份.原始的分區(qū)為L(zhǎng)eader 復(fù)制出的備份分區(qū)為Follower,Follower存放在與Leader不同的Broker上.在正常情況下,所有的讀寫(xiě)數(shù)據(jù)的工作全部由Leader完成,Follower只負(fù)責(zé)實(shí)時(shí)同步Leader中的數(shù)據(jù)變化.當(dāng)Leader不可用時(shí).兩個(gè)Follower會(huì)由Zookeeper組織完成選舉體態(tài)Leader.
ConsumerGroup:消費(fèi)者組,用于解決發(fā)布訂閱中多個(gè)消費(fèi)者共享一份數(shù)據(jù)負(fù)載均衡的問(wèn)題.一個(gè)組在消費(fèi)者客戶(hù)端中注冊(cè)一個(gè)offset組內(nèi)成員的消費(fèi)行為都會(huì)使offset發(fā)生改變.
Flink
Flink是一個(gè)分布式的計(jì)算引擎,能夠處理流式數(shù)據(jù)和離線(xiàn)數(shù)據(jù).(無(wú)邊界/有邊界)
核心API
DataSet : 用于處理離線(xiàn)數(shù)據(jù)
DataStream : 一般用于處理流式數(shù)據(jù),同時(shí)也支持將離線(xiàn)數(shù)據(jù)以流的形式來(lái)處理
Scala學(xué)習(xí)寶典(保姆級(jí))
前言
為什么要學(xué)習(xí)Scala
分布式高并發(fā)語(yǔ)言Go、R、Erlang等等為何選擇Scala?
Spark是大數(shù)據(jù)處理的核心方式,用scala語(yǔ)言編寫(xiě)!
Kafka分布式發(fā)布訂閱消息系統(tǒng),由LinkedIn捐給Apache,以極高的吞吐量著稱(chēng),是目前最火爆的MQ,用scala語(yǔ)言編寫(xiě)!
Flink最新一代分布式海量數(shù)據(jù)計(jì)算框架,Alibaba收購(gòu)并開(kāi)源,自己開(kāi)發(fā)Blink分支,Scala語(yǔ)言編寫(xiě)!
學(xué)前寄語(yǔ)
在我個(gè)人看來(lái),Scala是一門(mén)非常優(yōu)雅的語(yǔ)言,但優(yōu)雅的背后要付出的辛苦也很多,比如學(xué)習(xí)Scala的人都會(huì)說(shuō),Scala語(yǔ)法非常簡(jiǎn)潔,但這也意味著抽象級(jí)別比較高,對(duì)初學(xué)者而言不好理解。也會(huì)有人說(shuō),Scala語(yǔ)法非常靈活,一個(gè)功能可以有非常多的實(shí)現(xiàn)方法,可以說(shuō)條條大路通羅馬,那么代價(jià)就是對(duì)于初學(xué)者來(lái)說(shuō),路多了反而不好選擇。
所以在這里我對(duì)初學(xué)者的忠告是:在學(xué)習(xí)Scala前期,先走通一條路,屏蔽掉多余的干擾項(xiàng),可能我們第一次使用Scala實(shí)現(xiàn)的項(xiàng)目看起來(lái)是非常笨拙的,但是沒(méi)關(guān)系,任何的學(xué)習(xí)都是循序漸進(jìn)的,不要追求一蹴而就。走通之后再回頭,去尋找更好的替代方案。這樣才能享受學(xué)習(xí)。
Scala簡(jiǎn)介
Scala combines object-oriented and functional programming in one concise, high-level language. Scala’s static types help avoid bugs in complex applications, and its JVM and JavaScript runtimes let you build high-performance systems with easy access to huge ecosystems of libraries.
Scala是一個(gè)將面向?qū)ο蠛秃瘮?shù)式編程結(jié)合在一起的簡(jiǎn)潔的高級(jí)語(yǔ)言。Scala的靜態(tài)類(lèi)型有助于避免復(fù)雜應(yīng)用程序中的錯(cuò)誤,其可以運(yùn)行在JVM和JavaScript的特點(diǎn)使您可以輕松訪問(wèn)龐大的生態(tài)系統(tǒng)庫(kù)來(lái)構(gòu)建高性能系統(tǒng)。
Scala的誕生
Martin OrderSky馬丁 奧德斯基 是JVM開(kāi)發(fā)團(tuán)隊(duì)核心成員,是JDK1.5泛型,增強(qiáng)for循環(huán),自動(dòng)類(lèi)型轉(zhuǎn)換,JDK1.8Lambda等重要特性的作者.
在對(duì)JAVA的維護(hù)過(guò)程中,馬丁非常推崇JAVA的面向?qū)ο蠹袄厥?是James Gosling的小迷弟. 但作為編輯器開(kāi)發(fā)的狂熱愛(ài)好者的他,又覺(jué)得JAVA的語(yǔ)法過(guò)于繁瑣.所以相繼自己開(kāi)發(fā)了另外兩種語(yǔ)言Pizza和Scala.其中Scala被用于實(shí)驗(yàn)室科研后推廣開(kāi)源.在上邊提到JDK1.5和1.8的兩個(gè)版本中的新特性就是從Pizza和Scala中遷移而來(lái).
Scala誕生于2001年,但真正被人們所熟知并廣泛應(yīng)用于大數(shù)據(jù)開(kāi)發(fā)是在十多年之后.可以說(shuō)是Spark和Kafka帶火了Scala.
James Gosling曾在采訪中說(shuō),如果讓他選擇“今天使用的語(yǔ)言不是Java,那就是Scala”。
函數(shù)式編程
C:面向過(guò)程編程
Java:面向?qū)ο缶幊?br /> Scala:面向函數(shù)編程
函數(shù)式編程:將所有復(fù)雜的問(wèn)題的解決拆分為若干函數(shù)的處理,每一個(gè)函數(shù)可以去實(shí)現(xiàn)一部分功能,利用很多次函數(shù)的處理最終解決問(wèn)題。函數(shù)式編程相對(duì)于面向?qū)ο缶幊谈拥某橄?#xff0c;好處是代碼可以非常的簡(jiǎn)潔,更多的采用常量而不是變量來(lái)解決問(wèn)題,這樣額外帶來(lái)的好處是在線(xiàn)程并發(fā)時(shí)可以減少甚至杜絕多線(xiàn)程并發(fā)安全問(wèn)題,特別適合于應(yīng)用在處理高并發(fā)場(chǎng)景、分布式場(chǎng)景下的問(wèn)題。函數(shù)式編程可以使用高階函數(shù),函數(shù)在scala中是一等公民,可以更加靈活的進(jìn)行程序的編寫(xiě)。
函數(shù)式編程并不是面向?qū)ο缶幊痰陌l(fā)展,而是另外一種解決問(wèn)題的思路,兩者之間也并沒(méi)有絕對(duì)的好壞之分,在不同的場(chǎng)景中各有各的優(yōu)缺點(diǎn)。
總結(jié):Scala是一個(gè)面向?qū)ο蟮暮瘮?shù)式編程語(yǔ)言.
Scala和java的關(guān)系
java是由C語(yǔ)言開(kāi)發(fā),scala基于java,現(xiàn)在看來(lái)大部分情況下,青出于藍(lán)而勝于藍(lán)!
分布式開(kāi)發(fā)中會(huì)面對(duì)很多棘手的問(wèn)題,如面臨服務(wù)器之間的通信、遠(yuǎn)程調(diào)用、序列化、反序列化等等。但有了scala這一切變得輕松,它全部都做了內(nèi)部實(shí)現(xiàn)。讓我們?cè)L問(wèn)分布式集群環(huán)境就和訪問(wèn)單機(jī)一樣簡(jiǎn)單。
同時(shí)Scala無(wú)縫集成Java,Scala編譯器會(huì)先把源文件編譯成.class文件再運(yùn)行。Scala可以調(diào)用幾乎所有的Java類(lèi)庫(kù),也可以從Java應(yīng)用程序中調(diào)用Scala的代碼。它也可以訪問(wèn)現(xiàn)存的數(shù)之不盡的Java類(lèi)庫(kù),這讓用戶(hù)(潛在地)遷移到Scala更加容易。
Java => 編譯 => .class => JVM
Scala => 編譯 => .class => JVM
Scala => JVM(支持,但不推薦,不是解釋執(zhí)行)
擴(kuò)展:groovy、clojure(storm)都可以編譯成.class,利用JVM。
Scala的特點(diǎn)
Scala環(huán)境搭建
SDK下載安裝及測(cè)試
提示:Scala基于Java,需要提前安裝JDK并配置環(huán)境變量
官網(wǎng):https://www.scala-lang.org/
說(shuō)明: 編寫(xiě)本篇教程時(shí),Scala的最新版本為2.13.3,但是基于后續(xù)Spark\Kafka\Flink三個(gè)主流框架的版本及對(duì)Scala的版本要求.我們最終選擇Scala-2.12.7這個(gè)版本作為基礎(chǔ)環(huán)境. 2.11版本之后差別并不大,所以該文所有代碼預(yù)計(jì)在2.11\2.12\2.13版本環(huán)境中都可以正常運(yùn)行.
1.訪問(wèn)Scala官網(wǎng),找到所需安裝包進(jìn)行下載.https://www.scala-lang.org/download/all.html
在這里,我們選擇的是2.12.7這個(gè)版本進(jìn)行下載.
2.進(jìn)入2.12.7版本下載頁(yè)后,在尾部找到對(duì)應(yīng)系統(tǒng)安裝包進(jìn)行下載.
3.安裝Scala,雙擊msi包,一路下一步即可.注意中間在安裝目錄選擇時(shí),路徑不要有中文或空格.
選擇合適的目錄
4.檢查環(huán)境
5.Hello World
?
IDEA插件安裝
在IDEA的File菜單中打開(kāi)Settings窗口
選擇Plugins在Marketplace中搜索Scala,找到Scala插件后點(diǎn)擊Install.
等待插件下載完成,點(diǎn)擊重啟IEDA
如果網(wǎng)絡(luò)環(huán)境不佳無(wú)法自動(dòng)下載插件.此時(shí)需要手動(dòng)導(dǎo)入,具體導(dǎo)入方法可以參考我的另一篇文章:?https://blog.csdn.net/dcc15011003101/article/details/107805938
第一個(gè)Scala工程
創(chuàng)建一個(gè)新的工程
創(chuàng)建一個(gè)Object(至于什么是Object之后會(huì)詳細(xì)解釋)
命名為: cn.tedu.scalabasic.HelloWorld
選擇Object選項(xiàng)
編寫(xiě)代碼
右鍵運(yùn)行
結(jié)果
主方法
Scala基礎(chǔ)語(yǔ)法
注釋
Scala中注釋的寫(xiě)法與Java一致
package cn.tedu.scalabasic
/**
?* Scala基礎(chǔ)語(yǔ)法
?*/
object ScalaGrammar {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 1.注釋
? ? Scala中的注釋形式與Java中一致.包括文檔注釋,多行注釋,單行注釋
? ? ?*/
? ? /**
? ? ?* 這是一個(gè)文檔注釋
? ? ?*/
? ? /*
? ? 這是一個(gè)多行注釋
? ? ?*/
? ? //這是一個(gè)單行注釋
? }
}
代碼分隔
在Scala代碼中每行代碼的結(jié)尾不需要分號(hào)";"作為結(jié)束符(自動(dòng)推斷),也可以加分號(hào).
package cn.tedu.scalabasic
/**
?* Scala基礎(chǔ)語(yǔ)法
?*/
object ScalaGrammar {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 2.代碼分隔符
? ? 在Scala中,代碼行與行之間的分隔符與Java相同,使用分號(hào);,但是一般不需要寫(xiě),Scala實(shí)現(xiàn)了自動(dòng)推斷.
? ? ?*/
? ? println("再見(jiàn),劉沛霞");
? ? println("你好,張慎政")
? ? println("么么噠,董長(zhǎng)春")
? }
}
變量和常量定義
在Scala中變量和常量分別使用var和val來(lái)定義.可以聲明類(lèi)型但不必要(類(lèi)型自動(dòng)推斷).
其中,官方建議盡量不要使用var而是使用val來(lái)定義,有利于內(nèi)存回收.和線(xiàn)程的安全.
package cn.tedu.scalabasic
/**
?* Scala基礎(chǔ)語(yǔ)法
?*/
object ScalaGrammar {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 3.常量變量
? ? 在Scala中,變量使用var來(lái)定義,常量使用val定義
? ? 并且在定義變量和常量時(shí)一般都不寫(xiě)類(lèi)型.Scala按照上下文可以自動(dòng)推斷
? ? **重要**:在Scala中我們更推薦大家盡可能的使用常量來(lái)定義屬性,這更利于內(nèi)存回收.
? ? ?*/
? ? var a = 12
? ? val b = 10
? ? val c: Int = 11
? ? a += 1
? ? // ? ?b += 2 ?//編譯報(bào)錯(cuò),常量不可變
? ? println(a)
? ? println(b)
? }
}
標(biāo)識(shí)符
Scala 可以使用兩種形式的標(biāo)志符,字符數(shù)字和符號(hào)。
字符數(shù)字使用字母或是下劃線(xiàn)開(kāi)頭,后面可以接字母或是數(shù)字,符號(hào)"$“在 Scala 中也看作為字母。然而以”$“開(kāi)頭的標(biāo)識(shí)符為保留的 Scala 編譯器產(chǎn)生的標(biāo)志符使用,應(yīng)用程序應(yīng)該避免使用”$"開(kāi)始的標(biāo)識(shí)符,以免造成沖突。
同時(shí),Scala與Java相同的是同樣建議使用駝峰規(guī)則命名.
package cn.tedu.scalabasic
/**
?* Scala基礎(chǔ)語(yǔ)法
?*/
object ScalaGrammar {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 4.標(biāo)識(shí)符
? ? Scala標(biāo)識(shí)符規(guī)則與Java大致相同.不能以符號(hào)和數(shù)字開(kāi)頭(_和$可以).
? ? 其中以$例外一般不作為標(biāo)識(shí)符的開(kāi)頭使用,暫時(shí)不必深究.
? ? 命名格式推薦使用駝峰命名法:AaaBbb,aaaBbb,AAA_BBB
? ? 不能使用關(guān)鍵字和保留字命名
? ? ?*/
? ? val userName = "董長(zhǎng)春"
? ? // ? ?val if = 12 //編譯報(bào)錯(cuò),關(guān)鍵字和保留字不能用作標(biāo)識(shí)符
? }
}
關(guān)鍵字保留字
方法和操作符
在Scala中有這樣一句話(huà):操作符即方法,方法即操作符
意思是方法可以按照操作符的使用規(guī)則來(lái)使用,操作符也可以按照方法的方式使用
package cn.tedu.scalabasic
/**
?* Scala基礎(chǔ)語(yǔ)法
?*/
object ScalaGrammar {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 5.操作符和方法
? ? 在Scala中有這樣一句話(huà):操作符即方法,方法即操作符
? ? 意思是方法可以按照操作符的使用規(guī)則來(lái)使用,操作符也可以按照方法的方式使用
? ? ?*/
? ? val str = "123_456_789"
? ? val strs = str split "_" //這里以操作符的形式(1 + 2)使用split方法
? ? for (s <- strs) {
? ? ? println(s)
? ? }
? ? println(2.*(4)) //這里以方法的形式(a.split("_"))使用+操作符
? ? //對(duì)于沒(méi)有參數(shù)的方法,也可以不寫(xiě)括號(hào)
? ? val num: Int = 123
? ? println(num.toString())
? ? println(num.toString)
? }
}
Scala數(shù)據(jù)類(lèi)型
在Java中,分為基本數(shù)據(jù)類(lèi)型(8種) 和 引用類(lèi)型(繼承自O(shè)bject).其中基本數(shù)據(jù)類(lèi)型直接以字面量的形式賦值,沒(méi)有屬性和方法.
在Scala中數(shù)據(jù)類(lèi)型與Java的設(shè)計(jì)類(lèi)似,并且針對(duì)面向?qū)ο蠛秃瘮?shù)式編程做了更進(jìn)一步的優(yōu)化.
?
其中:
官方圖譜:
AnyVal
這里我們先對(duì)AnyVal做詳細(xì)講解
值類(lèi)型的定義
package cn.tedu.scalabasic
import scala.collection.immutable.StringOps
/**
?* AnyVal值類(lèi)型的聲明
?*/
object DataTypes {
? def main(args: Array[String]): Unit = {
? ? val a: Byte = 123
? ? println(a,a.getClass)
? ? val b: Short = 123
? ? println(b,b.getClass)
? ? val c: Int = 123
? ? println(c,c.getClass)
? ? val d: Long = 123L ?//此處加不加L都可以
? ? println(d,d.getClass)
? ? val e: Float = 1.23f ?//為區(qū)別Double,Float類(lèi)型后加f
? ? println(e,e.getClass)
? ? val f: Double = 1.23
? ? println(f,f.getClass)
? ? val g: Char = '@'
? ? println(g,g.getClass)
? ? val h: Boolean = false
? ? println(h,h.getClass)
? ? val i: Unit = "123" //不管這里賦值什么,他的值始終是()這是Unit的默認(rèn)值.
? ? println(i,i.getClass)
? ? /*
? ? ? 特殊說(shuō)明
? ? ? 雖然String是java.lang.String.在Scala中屬于AnyRef類(lèi)型,
? ? ? 但是在實(shí)際操作是會(huì)被隱式轉(zhuǎn)換為StringOps類(lèi)型屬于AnyVal
? ? ? 通過(guò)以下實(shí)驗(yàn)可以證明
? ? ?*/
? ? val j: String = "123"
? ? println(j,j.getClass) //(123,class java.lang.String)
? ? println(j.length(),j.length) ?//(3,3) 這里我們知道,java.lang.String類(lèi)中是沒(méi)有l(wèi)ength屬性的只有l(wèi)ength()方法
? ? val k: StringOps = "123"
? ? println(k,k.getClass) //(123,class scala.collection.immutable.StringOps) length在StringOps中定義
? }
}
值類(lèi)型的轉(zhuǎn)換
自動(dòng)類(lèi)型轉(zhuǎn)換
在Scala中類(lèi)型的轉(zhuǎn)換包括兩種,一種是值類(lèi)型轉(zhuǎn)換,另外一種是引用類(lèi)型轉(zhuǎn)換,這里我們先重點(diǎn)講解值類(lèi)型的轉(zhuǎn)換.
值類(lèi)型可以通過(guò)以下方式進(jìn)行轉(zhuǎn)換:
其轉(zhuǎn)換方向取決于長(zhǎng)度,只能由范圍小的類(lèi)型自動(dòng)轉(zhuǎn)換為范圍大的,不能大變小.
package cn.tedu.scalabasic
/**
?* 類(lèi)型轉(zhuǎn)換
?*/
object TypeTrans {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 自動(dòng)類(lèi)型轉(zhuǎn)換
? ? 在計(jì)算的過(guò)程中,值類(lèi)型會(huì)進(jìn)行自動(dòng)轉(zhuǎn)換,根據(jù)范圍由小到大
? ? Byte->Short->Int->Long->Float->Double
? ? ? ? ? ? ? ? ? ↑
? ? ? ? ? ? ? ? ?Char
? ? ?*/
? ? var a: Int = 12
? ? var b: Byte = 1
? ? var c: Char = 'a'
? ? var d: Long = 12
? ? var e: Double = 11.1
? ? var f: Short = 3
? ? var g: Float = 3.2f
? ? println(a+b,(a+b).getClass)
? ? println(a+c,(a+c).getClass)
? ? println(a+d,(a+d).getClass)
? ? println(a+e,(a+e).getClass)
? ? println(a+f,(a+f).getClass)
? ? println(d+g,(d+g).getClass)
? }
}
?
說(shuō)明:浮點(diǎn)數(shù)32位的范圍大于Long的64位,由轉(zhuǎn)換公式?jīng)Q定.
強(qiáng)制類(lèi)型轉(zhuǎn)換
范圍大的數(shù)據(jù)類(lèi)型通過(guò) .toxxx 實(shí)現(xiàn)向范圍小的數(shù)據(jù)類(lèi)型強(qiáng)制轉(zhuǎn)換,注意可能會(huì)造成精度的缺失.
package cn.tedu.scalabasic
/**
?* 類(lèi)型轉(zhuǎn)換
?*/
object TypeTrans {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 強(qiáng)制類(lèi)型轉(zhuǎn)換
? ? 范圍大的數(shù)據(jù)類(lèi)型通過(guò) .toxxx 實(shí)現(xiàn)向范圍小的數(shù)據(jù)類(lèi)型強(qiáng)制轉(zhuǎn)換,注意可能會(huì)造成精度的缺失.
? ? ?*/
? ? val h: Int = 12
? ? val i: Double = 2.12
? ? val j: Int = (h + i).toInt
? ? println(j)
? }
}
?
值類(lèi)型和String類(lèi)型之間的相互轉(zhuǎn)換
?
package cn.tedu.scalabasic
/**
?* 類(lèi)型轉(zhuǎn)換
?*/
object TypeTrans {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 值類(lèi)型和String類(lèi)型之間的相互轉(zhuǎn)換
? ? ?*/
? ? //值類(lèi)型轉(zhuǎn)換為String類(lèi)型有兩種方式,分別是a+"" 和 a.toString
? ? val k:Int = 12
? ? println(k+"",(k+"").getClass)
? ? val l:Int = 12
? ? println(l.toString,(k.toString).getClass)
? ? //String類(lèi)型數(shù)據(jù)轉(zhuǎn)換為值類(lèi)型的前提是可轉(zhuǎn),使用.toXxx
? ? val m:String = "123"
// ? ?val m:String = "12a" ?//報(bào)錯(cuò):java.lang.NumberFormatException
? ? println(m.toInt,m.toInt.getClass)
? }
}
?
運(yùn)算符
算數(shù)運(yùn)算符
Scala中的算數(shù)運(yùn)算符與Java基本一致,唯一不同是沒(méi)有++和–.
package cn.tedu.scalabasic
/**
?* Scala中的操作符
?*/
object ScalaOperator {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 算數(shù)運(yùn)算符
? ? ?*/
? ? val a = 13
? ? val b = 3
? ? println(a + b)
? ? println(a - b)
? ? println(a * b)
? ? println(a / b)
? ? println(a / 3.0) ?//如果在除法運(yùn)算時(shí)需要精確值,需要有至少一個(gè)浮點(diǎn)型
? ? println(a % b)
? }
}
賦值運(yùn)算符
Scala中的賦值運(yùn)算符與Java基本一致
package cn.tedu.scalabasic
/**
?* Scala中的操作符
?*/
object ScalaOperator {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 賦值運(yùn)算符
? ? ?*/
? ? var c = 3 //將3這個(gè)值賦值給變量a
? ? c += 3
? ? println(c)
? ? c -= 3
? ? println(c)
? ? c *= 3
? ? println(c)
? ? c /= 3
? ? println(c)
? ? c %= 3
? ? println(c)
? }
}
關(guān)系運(yùn)算符
Scala中的關(guān)系運(yùn)算符與Java基本一致
package cn.tedu.scalabasic
/**
?* Scala中的操作符
?*/
object ScalaOperator {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 關(guān)系運(yùn)算符
? ? ?*/
? ? println(a>b)
? ? println(a>=b)
? ? println(a<b)
? ? println(a<=b)
? ? println(a==b)
? ? println(a!=b)
? }
}
邏輯運(yùn)算符
Scala中的邏輯運(yùn)算符與Java基本一致,但是在取反操作時(shí)不能像Java一樣多層取反.
package cn.tedu.scalabasic
/**
?* Scala中的操作符
?*/
object ScalaOperator {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 邏輯運(yùn)算符
? ? ?*/
? ? var bool1 = true
? ? var bool2 = false
? ? println(bool1 && bool2)
? ? println(bool1 || bool2)
? ? println(!bool2) //Scala不支持多層取反(!!!!!true)
? }
}
位運(yùn)算符
Scala中的位運(yùn)算符與Java基本一致,了解即可.
流程控制
程序的執(zhí)行順序需要根據(jù)需求進(jìn)行相應(yīng)的控制,比如執(zhí)行的順序,執(zhí)行條件,執(zhí)行次數(shù)等.
順序結(jié)構(gòu)
Scala像大部分語(yǔ)言一樣,代碼一般按照從上到下的順序執(zhí)行.
一行代碼中安裝從左到右的順序執(zhí)行,同一行內(nèi)如果有括號(hào),先算括號(hào)里.
數(shù)學(xué)計(jì)算中遵循先乘除后加減.
package cn.tedu.scalabasic
/**
?* 流程控制
?*/
object ProcessControl {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 順序結(jié)構(gòu)
? ? ?*/
? ? println("Hello World")
? ? println(1+2+"Hello World"+3+2*2+(4+5))
? }
}
分支結(jié)構(gòu)
在Scala分支結(jié)構(gòu)中,只有if…else if…else 沒(méi)有Java中的switch…case(模式匹配)
需要注意的是if分支結(jié)構(gòu)是可以有返回值的.所以可以使用if語(yǔ)句替代Scala中沒(méi)有的三元運(yùn)算符.
與Java一致的是,分支結(jié)構(gòu)可以多層嵌套.
package cn.tedu.scalabasic
/**
?* 流程控制
?*/
object ProcessControl {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 分支結(jié)構(gòu)
? ? ?*/
? ? val age = 19
? ? if (age >= 18) {
? ? ? println("你已經(jīng)成年了")
? ? } else if (age >= 500) {
? ? ? println("你已經(jīng)成精了")
? ? } else {
? ? ? println("你還是個(gè)孩子")
? ? }
? ? //在Scala中沒(méi)有三元運(yùn)算符 a?b:c,使用if...else代替
? ? var result = if (age >= 18) "你已經(jīng)成年了" else "你還是個(gè)孩子"
? ? println(result)
? }
}
循環(huán)結(jié)構(gòu)
for循環(huán)
在Scala中for循環(huán)用于控制程序執(zhí)行次數(shù),與Java一致,同時(shí)具備了更加豐富的功能.
package cn.tedu.scalabasic
/**
?* 流程控制
?*/
object ProcessControl {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 循環(huán)結(jié)構(gòu)-for
? ? ?*/
? ? for (i <- 1 to 10) {
? ? ? println(i)
? ? }
? ? //九九乘法表
?? ?for (i <- 1 to 9) {
? ? ? for (j <- 1 to i) {
?? ??? ?//print(j + "*" + i + "=" + i * j + "\t")
? ? ? ? //在Scala中變量和字符串的拼接可以簡(jiǎn)化為占位符
? ? ? ? print(s"${j} * ${i} = ${i*j}\t")
? ? ? }
? ? ? println()
? ? }
? ? //簡(jiǎn)寫(xiě)
? ? for (i <- 1 to 9; j <- 1 to i) {
? ? ? print(s"${j} * ${i} = ${i*j}\t")
? ? ? if (i == j) println()
? ? }
? ? //循環(huán)條件,守衛(wèi),步長(zhǎng)
? ? for(i <- 1 to 10 if i % 2 == 0) println(i)
? ? //推導(dǎo)式:生成一個(gè)2到10的偶數(shù)集合
? ? var nums = for(i <- 1 to 10 if i % 2 == 0) yield i
? ? println(nums)
? }
}
?
while循環(huán)
Scala中while與Java中寫(xiě)法和用法都一致.但是更推薦使用for,因?yàn)閒or更加簡(jiǎn)潔.
package cn.tedu.scalabasic
/**
?* 流程控制
?*/
object ProcessControl {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 循環(huán)結(jié)構(gòu)-while
? ? ?*/
? ? var num1 = 0
? ? while (num1 <= 10) {
? ? ? num1 += 1
? ? }
? ? println(num1)
? ? var num2 = 0
? ? do {
? ? ? num2 += 1
? ? } while (num2 <= 10)
? ? println(num2)
? }
}
?
break()和breakable
在Scala中沒(méi)有break和continue想要使用類(lèi)似功能只能用scala.util.control.Breaks._工具
package cn.tedu.scalabasic
/**
?* 流程控制
?*/
object ProcessControl {
? def main(args: Array[String]): Unit = {
? ? /*
? ? break()和breakable
? ? ?*/
? ? ?//導(dǎo)包
? ? import scala.util.control.Breaks._
? ? //break
? ? breakable {
? ? ? for (i <- 1 to 10) {
? ? ? ? println(i)
? ? ? ? if (i == 6) break()
? ? ? }
? ? }
? ? //continue
? ? for (i <- 1 to 10) {
? ? ? breakable {
? ? ? ? if (i % 2 == 0) break()
? ? ? ? println(i)
? ? ? }
? ? }
? }
}
?
代碼塊
在Java中我們學(xué)過(guò)靜態(tài)代碼塊,在Scala中也有代碼塊的概念,就是用大括號(hào)括起來(lái)的一段代碼.并且在Scala中代碼塊是可以有返回值的.
package cn.tedu.scalabasic
/**
?* 流程控制
?*/
object ProcessControl {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 代碼塊
? ? */
? ? val block = {
? ? ? println("代碼")
? ? ? val v1 = 12
? ? ? val v2 = 14
? ? ? v1 + v2 ?//最后一行的表達(dá)式為返回值
? ? }
? ? println(block)
? }
}
方法和函數(shù)
在Scala中方法和函數(shù)是不一樣的.一般情況下在使用時(shí)并不需要特殊區(qū)分.
方法
Scala中的方法定義與Java不同更加簡(jiǎn)潔.
一般情況下返回值類(lèi)型可以省略.遞歸方法除外.
return可以省略,默認(rèn)方法體中最后一行被返回.
只有一行代碼的時(shí)候大括號(hào)也可以省略.
當(dāng)返回值類(lèi)型為Unit(沒(méi)有返回值)時(shí),=也可以省略不寫(xiě),也就是說(shuō)如果不寫(xiě)等號(hào)該方法不會(huì)返回任何數(shù)據(jù).這種形式在Scala中叫做"過(guò)程"
package cn.tedu.scalafunction
/**
?* 方法
?*/
object Method {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 方法的定義
? ? ?*/
? ? def getSum1(a:Int,b:Int):Int = {
? ? ? return a+b
? ? }
? ? //返回值類(lèi)型可以省略(自動(dòng)推斷)
? ? //return可以省略(默認(rèn)返回最后一行)
? ? //{}可以省略(只有一行代碼)
? ? def getSum2(a:Int,b:Int)= a + b
? ??
? ? val sum1 = getSum1(1,2)
? ? val sum2 = getSum2(3,4)
? ??
? ? println(sum1)
? ? println(sum2)
? ? //沒(méi)有返回值時(shí),=等號(hào)可以不寫(xiě).這種形式在Scala中叫做:過(guò)程
? ? def sayHello() {
? ? ? println("Hello,World")
? ? ? return 1 ?//即使寫(xiě)了返回1,因?yàn)闆](méi)有等號(hào)= 方法也不會(huì)返回任何數(shù)據(jù).
? ? }
? ? val hello = sayHello()
? ? println(hello)
? }
}
?
遞歸
方法內(nèi)部調(diào)用自己,即為遞歸
遞歸方法定義時(shí)不能省略返回值類(lèi)型
package cn.tedu.scalafunction
/**
?* 方法
?*/
object Method {
? def main(args: Array[String]): Unit = {
? ? //遞歸方法定義時(shí)必須聲明返回值
? ? def getFactorial(n: Int): Int = {
? ? ? if (n == 1) n else n * getFactorial(n - 1)
? ? }
? ? val factorial = getFactorial(5)
? ? println(factorial)
? }
}
?
方法的參數(shù)
默認(rèn)參數(shù)
在方法的定義時(shí),我們有時(shí)會(huì)遇到這樣的需求: 某些參數(shù)通常是不變的數(shù)據(jù)只有少數(shù)情況下才會(huì)變化.如果大多數(shù)情況下都需要手動(dòng)傳入同樣值不符合編程中復(fù)用的原則.默認(rèn)參數(shù)就可以解決這類(lèi)問(wèn)題.
package cn.tedu.scalafunction
/**
?* 方法
?*/
object Method {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 默認(rèn)參數(shù)
? ? ?*/
? ? def getUserInfo(name:String,age:Int,addr:String = "張家口"):String = {
? ? ? s"${name}來(lái)自${addr},今年${age}歲了"
? ? }
? ? val info1 = getUserInfo("董長(zhǎng)春",12)
? ? val info2 = getUserInfo("馬夢(mèng)詩(shī)",12)
? ? val info3 = getUserInfo("劉沛霞",12,"天津")
? ? println(info1)
? ? println(info2)
? ? println(info3)
? }
}
?
指定參數(shù)
指定參數(shù)時(shí)指,在調(diào)用方法是通過(guò)指定參數(shù)名來(lái)改變參數(shù)傳遞的前后順序.
package cn.tedu.scalafunction
/**
?* 方法
?*/
object Method {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 指定參數(shù)
? ? ?*/
? ? def getProduct(a: Int = 5, b: Int = 10) = (a + 3) * b
? ? //改變參數(shù)傳入的順序
? ? println(getProduct(b = 4, a = 3))
? ? //避免在參數(shù)有默認(rèn)值時(shí)錯(cuò)傳
? ? println(getProduct(b = 1))
? }
}
可變參數(shù)
當(dāng)方法的參數(shù)列表中有多個(gè)不確定的參數(shù)時(shí),可以是用可變參數(shù),與Java類(lèi)似.
可變參數(shù)用數(shù)組來(lái)保存,可以直接調(diào)用數(shù)組的方法.
如果參數(shù)列表中既有普通參數(shù),也有可變參數(shù),可變參數(shù)必須寫(xiě)在最后.
package cn.tedu.scalafunction
/**
?* 方法
?*/
object Method {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 可變參數(shù)
? ? ?*/
? ? def getSum4(nums:Int*) = nums.sum //可變參數(shù)是用數(shù)組保存的,可以直接使用數(shù)組的方法.
? ? //需要注意的是,如果參數(shù)列表中既有普通參數(shù),也有可變參數(shù),可變參數(shù)需要寫(xiě)在最后.
? ? //def getLogs(logs:String*,id:Int) = {} //編譯錯(cuò)誤:*-parameter must come last
? }
}
方法的調(diào)用
在Scala中方法的調(diào)用也是非常靈活的,我們來(lái)總結(jié)一下.
后綴調(diào)用
最普通的調(diào)用方式就是后綴調(diào)用,這與Java中是一致的.都是對(duì)象.methodName(參數(shù))的形式.
中綴調(diào)用
中綴調(diào)用其實(shí)在前邊已經(jīng)接觸過(guò),就是方法即運(yùn)算法,運(yùn)算符及方法的體現(xiàn).
比如:1 to 10.就是1.to(10)
大括號(hào)調(diào)用
當(dāng)參數(shù)只有一個(gè)時(shí),也可以將小括號(hào)替換為大括號(hào).比如: 對(duì)象.methodName{參數(shù)},用的不多.
無(wú)括號(hào)調(diào)用
當(dāng)沒(méi)有參數(shù)時(shí),方法的調(diào)用可以不寫(xiě)括號(hào),比如:array.sum
惰性加載
為了解決資源推遲加載,優(yōu)化啟動(dòng)速度,區(qū)別加載順序等問(wèn)題,Scala中設(shè)計(jì)了一個(gè)惰性加載的概念.
所有被lazy修飾的val所指向的資源不會(huì)直接加載,而是延遲到使用時(shí)才會(huì)加載.
需要注意的是,lazy只能修飾val 不能修飾var
當(dāng)用于接收方法返回值得val被lazy修飾是,這個(gè)方法會(huì)惰性加載.叫做惰性方法.
這種惰性加載的形式在Java中也有,只不過(guò)Java沒(méi)有原生支持,而是通過(guò)代碼邏輯來(lái)實(shí)現(xiàn),叫做懶加載,比如單例中的懶漢式.在Spring等對(duì)象管理框架中也有懶加載的概念.
package cn.tedu.scalafunction
/**
?* 方法
?*/
object Method {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 惰性方法(類(lèi)似Java中的懶加載)
? ? ?*/
? ? def getSum3(a:Int,b:Int) = {
? ? ? println("getSum3已經(jīng)加載")
? ? ? a + b
? ? }
// ? ?val sum3 = getSum3(1,2)
? ? lazy val sum3 = getSum3(1,2)
? ? println(sum3)
? }
}
函數(shù)
在Scala中函數(shù)與方法是不同的.方法依附于對(duì)象,而函數(shù)本身就是對(duì)象.
函數(shù)的定義方式也與方法不同.
object Function {
? def main(args: Array[String]): Unit = {
? ? /*
? ? 函數(shù)的定義
? ? 1.函數(shù)本身是一個(gè)對(duì)象.
? ? 2.函數(shù)參數(shù)列表和函數(shù)體之間是 => 來(lái)鏈接
? ? 3.函數(shù)不需要寫(xiě)返回值類(lèi)型.
? ? 4.函數(shù)定義時(shí)的變量名就是函數(shù)名,也就是這個(gè)對(duì)象的引用,調(diào)用時(shí)使用函數(shù)名(參數(shù))的形式調(diào)用.
? ? 5.函數(shù)可以直接用lazy修飾作為惰性函數(shù).
? ? ?*/
? ? val getSum = (a:Int,b:Int) => {a + b}
? ? println(getSum(1,2))
? ? val printMsg = () => {println("Hello")}
? ? printMsg()
? ? lazy val getMax = (v1:Int,v2:Int) => {if (v1>v2) v1 else v2}
? ? println(getMax(2, 3))
? ??
? ? /*
? ? 方法轉(zhuǎn)函數(shù)
? ? 有時(shí)候我們需要將一段邏輯作為參數(shù)傳遞,但是方法不支持傳遞,可以將其轉(zhuǎn)化為函數(shù).
? ? 通過(guò)本案例的輸出結(jié)果,我們也可驗(yàn)證,函數(shù)是對(duì)象,而方法不是.
? ? ?*/
? ??
? ? def getInfo() = {println("我叫董長(zhǎng)春")}
? ? println(getInfo)
? ? val toFunction = getInfo _
? ? println(toFunction)
? }
}
類(lèi)和對(duì)象
回顧面向?qū)ο?/h2>
在Java的學(xué)習(xí)過(guò)程中,面向?qū)ο鬅o(wú)疑是重中之重.而Scala是一門(mén)面向?qū)ο蟮暮瘮?shù)式編程語(yǔ)言,所以面向?qū)ο蟮母拍罨蛘咚枷朐赟cala學(xué)習(xí)過(guò)程中也是不能忽視的.
什么是面向?qū)ο?/h3>
面向?qū)ο笫且环N編程思想,是相對(duì)于面向過(guò)程的又一層高級(jí)抽象.
我們將一系列事物的特性或者功能抽象出來(lái)并對(duì)其進(jìn)行封裝,這個(gè)封裝結(jié)果就是類(lèi),而屬于這個(gè)類(lèi)的所有個(gè)體就是這個(gè)類(lèi)的對(duì)象.
面向?qū)ο蟮奶攸c(diǎn)
封裝: 保證安全性
繼承: 保證復(fù)用性
多態(tài): 保證拓展性
類(lèi)的定義和對(duì)象創(chuàng)建
Scala中簡(jiǎn)單的類(lèi)定義與Java相同,內(nèi)部可以定義成員屬性和成員方法.
package cn.tedu.scalaoop
/**
?* 定義一個(gè)類(lèi)
?*/
class Person {
? //初始化屬性有三種方式
? var name:String = "" ?//姓名
? var age:Int = _ ? ? ? //年齡
? var addr = "" ? ? ? ? //地址
? def sayHello(){println(s"大家好我是${name},今年${age}歲了,來(lái)自${addr}.")}
}
對(duì)象的創(chuàng)建方式與Java也類(lèi)似,通過(guò)new關(guān)鍵字實(shí)現(xiàn)對(duì)象的創(chuàng)建
在使用空參構(gòu)造時(shí),類(lèi)名后的括號(hào)可以省略.
對(duì)象可以訪問(wèn)類(lèi)的公共屬性和方法.
package cn.tedu.scalaoop
/**
?* 創(chuàng)建對(duì)象
?*/
object PersonObject {
? def main(args: Array[String]): Unit = {
? ? val p1 = new Person()
? ? //構(gòu)造方法為空時(shí),括號(hào)可以省略
? ? val p2 = new Person
? ? p2.name = "董長(zhǎng)春"
? ? p2.age = 18
? ? p2.addr = "張家口"
? ? p2.sayHello()
? }
}
訪問(wèn)權(quán)限修飾符
Scala中訪問(wèn)權(quán)限修飾符與Java稍有不同,但是功能是一致的.
Scala中共有四種訪問(wèn)權(quán)限修飾符
包括:private \ private[this] \ protected \ 默認(rèn)
| private[this] | 作用域私有的,只能在范圍內(nèi)中訪問(wèn),對(duì)于其他私有 |
| private | 類(lèi)私有的,只能在本類(lèi)訪問(wèn) |
| protected | 受保護(hù)的,只能在本類(lèi)及其子類(lèi)中訪問(wèn) |
| 默認(rèn) | 公共的(public)全局可訪問(wèn) |
一般情況下,開(kāi)發(fā)中更多的使用到默認(rèn)的,和private私有的.
package cn.tedu.scalaoop
/**
?* 定義一個(gè)動(dòng)物類(lèi)
?*/
class Animal {
? var name = ""
? private var age = 0
? protected var color = ""
? private[this] var eat = ""
? def sayHello(){println(name,age,color,eat)}
}
?
package cn.tedu.scalaoop
object AnimalObject {
? def main(args: Array[String]): Unit = {
? ? val animal = new Animal
? ? animal.name = "驢"
? ? //非公有不能訪問(wèn)
// ? ?animal.age
// ? ?animal.color
// ? ?animal.eat
? }
? class Donkey extends Animal{
? ? var animal = new Animal
? ? animal.name
// ? ?animal.age ?//私有不能訪問(wèn)
? ? animal.color ?//子類(lèi)可以訪問(wèn)protected修飾的屬性
// ? ?animal.eat ?//私有不能訪問(wèn)
? }
}
?
構(gòu)造器
像Java創(chuàng)建對(duì)象一樣,Scala在創(chuàng)建對(duì)象的時(shí)候也是調(diào)用構(gòu)造器,而Scala中構(gòu)造器的寫(xiě)法與Java不用,直接定義在類(lèi)名之后的小括號(hào)里.
單例對(duì)象
伴生類(lèi)和伴生對(duì)象
private[this]權(quán)限修飾
apply()方法
繼承
特質(zhì)Trait
包和樣例
容器
數(shù)組
元組
列表
集合
映射
迭代器
函數(shù)式編程
模式匹配
IO
高階函數(shù)
隱式轉(zhuǎn)換
泛型
集合
Actor
Akka
- ?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的IDEA Git操作(三)使用 cherry-pick、交互式 rebase 自由修改提交树的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 关于Windows 2003 安装Int
- 下一篇: md5和sha1文件完整性校验