首页
技术博客
PHP教程
数据库技术
前端开发
HTML5
Nginx
php论坛
新用户注册
|
会员登录
PHP教程
技术博客
编程问答
PNG素材
编程语言
前端技术
Android
PHP教程
HTML5教程
数据库
Linux技术
Nginx技术
PHP安全
WebSerer
职场攻略
JavaScript
开放平台
业界资讯
大话程序猿
登录
极速注册
取消
热门标签 | HotTags
rsa
utf-8
match
emoji
ascii
testing
controller
lua
header
usb
bytecode
c语言
range
js
stream
dockerfile
int
plugins
less
blob
merge
filter
node.js
jar
hashtable
cSharp
tree
process
text
php7
request
integer
list
heap
datetime
cPlusPlus
default
const
input
dagger
runtime
php5
fetch
email
php8
regex
import
include
join
foreach
vba
scala
vbscript
window
ip
yaml
case
export
iostream
erlang
actionscrip
python2
audio
httpclient
web3
typescript
subset
search
python3
keyword
buffer
config
cmd
httprequest
require
java
hashcode
install
solr
当前位置:
开发笔记
>
编程语言
> 正文
Scala学习指南:从零开始掌握基础
作者:爱与嫉妒咋 | 来源:互联网 | 2024-11-07 18:07
本指南从零开始介绍Scala编程语言的基础知识,重点讲解了Scala解释器REPL(读取-求值-打印-循环)的使用方法。REPL是Scala开发中的重要工具,能够帮助初学者快速理解和实践Scala的基本语法和特性。通过详细的示例和练习,读者将能够熟练掌握Scala的基础概念和编程技巧。
一、Scala解释器的使用
REPL:Read(取值)-> Evaluation(求值)-> Print(打印)-> Loop(循环)
scala解释器也被称为REPL,会快速编译scala代码为字节码,然后交给JVM来执行。
计算表达式:在scala>命令行内,键入scala代码,解释器会直接返回结果。
如果你没有指定变量来存放这个值,那么值默认的名称为res,而且会
显示结果的数据类型,比如Int、Double、String等等。
例如,输入1 + 1,会看到res0: Int = 2
内置变量:在后面可以继续使用res这个变量,以及它存放的值。
例如,"Hi, " + res0,返回res2: String = Hi, 2
自动补全:在scala>命令行内,可以使用Tab键进行自动补全。
二、声明变量
声明val常量:可以声明val常量来存放表达式的计算结果。
例如,val result = 1 + 1
但是常量声明后,是无法改变它的值的,否则会返回error: reassignment
to val的错误信息。
声明var变量:如果要声明值可以改变的引用,可以使用var变量。
例如,var myresult = 1,myresult = 2
但是在Scala程序中,通常建议使用val,也就是常量。
因为在Spark的大型复杂系统中,需要大量的网络传输数据,
如果使用var,值可能被错误的更改,所以建议多使用val。
三、数据类型与操作符
1》基本数据类型: Byte、 Char、 Short、 Int、 Long、 Float、 Double、 Boolean。
Scala的数据类型统一都是类。 Scala自己会负责基本数据类型和引用类型的转换操作。
使用以上类型, 直接就可以调用大量的函数, 例如, 1.toString(), 1.to(10)。
类型的加强版类型: Scala使用很多加强类给数据类型增加了上百种增强的功能或函数。
·例如, String类通过StringOps类增强了大量的函数, "Hello".intersect(" World")。
·例如, Scala还提供了RichInt、 RichDouble、 RichChar等类型, RichInt就提供了to函数, 1.to(10), 此处Int先隐式转换为RichInt,然后再调用其to函数。
2》基本操作符: Scala的算术操作符与Java的算术操作符也没有什么区别, 比如+、 -、 *、 /、 %等, 以及&、 |、 ^、 >>、 <<等。
但是, 在Scala中, 这些操作符其实是数据类型的函数, 比如1 + 1, 可以写做1.+(1)
例如, 1.to(10), 又可以写做1 to 10
注:Scala中没有提供++、--操作符
, 我们只能使用
+
和
-
, 比如
counter = 1
,
counter++
是错误的, 必须写做
counter += 1
3》除了方法之外,Scala还提供函数
数学函数:sqrt() pow() min()
引入特定包时使用import 包名._;
import scala.math._ ,_是通配符,类似Java中的*
四、流程控制结构
1、if表达式的定义: 在Scala中, if表达式是有值的, 就是if或者else中最后一行语句返回的值。
例如, val age = 30; if (age > 18) 1 else 0
可以将if表达式赋予一个变量, 例如, val isAdult = if (age > 18) 1 else 0
另外一种写法, var isAdult = -1; if(age > 18) isAdult = 1 else isAdult = 0, 但是通常使用上一种写法
2、if表达式的类型推断: 由于if表达式是有值的, 而if和else子句的值类型可能不同, 此时if表达式的值是什么类型呢?
Scala会自动进行推断, 取两个类型的公共父类型Any。
例如, if(age > 18) 1 else 0, 表达式的类型是Int, 因为1和0都是Int
例如, if(age > 18) "adult" else 0, 此时if和else的值分别是String和Int, 则表达式的值是Any, Any是String和Int的公共父类型。
如果if后面没有跟else, 则默认else的值是Unit, 也用()表示, 类似于Java中的void或者null。
例如, val age = 12; if(age > 18) "adult"。 此时就相当于if(age > 18) "adult" else ()。
3、将if语句放在多行中: 默认情况下, REPL只能解释一行语句, 但是if表达式通常需要放在多行。
可以使用{}的方式, 比如以下方式, 或者使用:paste和ctrl+D的方式。
if(age > 18) { "adult"
} else if(age > 12) "teenager" else "children"
注:默认情况下, Scala不需要语句终结符, 默认将每一行作为一个语句
4、一行放多条语句: 如果一行要放多条语句, 则必须使用语句终结符
例如, 使用分号作为语句终结符, var a, b, c = 0; if(a <10) { b = b + 1
;
c = c + 1 }
通常来说, 对于多行语句, 还是会使用花括号的方式
var a, b, c = 0;if(a <10) {
b = b + 1;c = c + 1}
5、块表达式: 块表达式, 指的就是{}中的值, 其中可以包含多条语句, 最后一个语句的值就
是块表达式的返回值。
例如, var d = if(a <10) { b = b + 1; c + 1 }
6、输入和输出
print和println: print打印时不会加换行符, 而println打印时会加一个换行符。
printf可以用于进行格式化,例如, printf("Hi, my name is %s, I'm %d years old .", "Leo", 30)
readLine: readLine允许我们从控制台读取用户输入的数据, 类似于Java中的System.in和Scanner的作用。
综合案例:使用paste和ctrl+D
val name = readLine("Welcome to Game House. Please tell me your name: ")
print("Thanks. Then please tell me your age: ")
val age = readInt()
if(age > 18) {
printf("Hi, %s, you are %d years old, so you are legel to come here!", name, age)
} else {
printf("Sorry, boy, %s, you are only %d years old. you are illegal to come here!",
name, age)
}
五、循环
1、Scala拥有与Java相同的while和do-while循环
但没有与for(初始化变量;判断条件;更新变量)循环直接对应的对构。
Scala中的for:
for(i
<-
表达式)
,让变量i遍历<-右边表达式的所有值。
注意:
1、在for循环的变量之前并没有val或var的指定,该变量的类型是集合的元素类型。
2、循环变量的作用域一直持续到循环结束
3、to 和 until,两者得到都是集合,区别如下:
scala> 1 to 10 (包含10)
res8: scala.collection.immutable.Range.Inclusive = Range(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
scala> 1 until 10 (不包含10)
res10: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
4、循环的几种遍历方式
一、直接遍历------遍历字符串
二、求和---------1到8的和
三、以 变量<-表达式 的形式提供多个生成器,用分号将它们隔开(嵌套循环)
for(i<- 1 to 9;j<- 1 to i){
if(i==j) println(j+"*"+i+"="+j*i)
else print(j+"*"+i+"="+j*i+"\t")
}
四、在循环中使用变量
for(i<- 1 to 6;tem=2*i-1;j<- 1 to tem){
print("*");if(j==tem) {println()}}
五、守卫式,即在for循环中添加过滤条件if语句
for(i<- 1 to 3;j<- 1 to 3 if i!=j) print((10*i+j)+" ")
六、推导式
如果for循环的循环体以yield开始,则该循环会构造出一个集合,每次迭代生成集合中的一个值。
六、函数
1、函数的分类
单行函数:def sayHello(name: String) = print("Hello, " + name)
多行函数:如果函数体中有多行代码, 则可以使用代码块的方式包裹多行代码, 代码块中最后一行
的返回值就是整个函数的返回值。 与Java中不同, 不能使用return返回值。
比如如下的函数, 实现累加的功能:
def sum(n:
Int
) :
Int
= {
var sum = 0;
for(i <- 1 to n) sum += i
sum}
2、函数的定义与调用
在Scala中定义函数时, 需要定义函数的
函数名、 参数、 函数体。
def sayHello(name: String, age: Int) = {
if (age > 18) { printf("hi %s, you are a big boy\n", name); age }
else { printf("hi %s, you are a little boy\n", name); age}}
调用:sayHello("leo", 30)
注:Scala要求必须给出所有参数的类型, 但是不一定给出函数返回值的类型。
只要右侧的函数体中不包含递归的语句, Scala就可以自己根据右侧的表达式推断出返回类型。
3、递归函数与返回类型
如果在函数体内递归调用函数自身, 则必须给出函数的返回类型。
例如, 实现经典的斐波那契数列:
def feibo(n:Int):Int={
if(n<=2) 1
else feibo(n-1)+feibo(n-2)}
例如如下阶乘:
4、参数
1》默认参数
在Scala中, 有时我们调用某些函数时, 不希望给出参数的具体值, 而希望使用参数自身默认的值, 此时就在定义函数时使用默认参数。
def sayHello(firstName: String, middleName: String = "William", lastName:
String = "Croft") = firstName + " " + middleName + " " + lastName
如果给出的参数不够, 则会从左往右依次应用参数。
Java与Scala实现默认参数的区别如下:
-----------------------------------------------------------------------------------
Java:
public void sayHello(String name, int age) {
if(name == null) {
name = "defaultName"
} if(age == 0) {
age = 18
}}
sayHello(null, 0)
-----------------------------------------------------------------------------------
Scala:
def sayHello(name: String, age: Int = 20) {
print("Hello, " + name + ", your age is " + age)}
sayHello("leo")
2》带名参数
在调用函数时, 也可以不按照函数定义的参数顺序来传递参数, 而是使用带名参数的方式来
传递。如:sayHello(firstName = "Mick", lastName = "Nina", middleName = "Jack")
还可以混合使用未命名参数和带名参数, 但是未命名参数必须排在带名参数前面。如下:
正确:sayHello("Mick", lastName = "Nina", middleName = "Jack")
错误:sayHello("Mick", firstName = "Nina", middleName = "Jack")
3》使用序列调用变长参数
在如果要将一个已有的序列直接调用变长参数函数, 是不对的。 比如val s = sum(1 to 5)。
此时需要使用Scala特殊的语法将参数定义为序列, 让Scala解释器能够识别。
这种语法非常有用!Spark的源码中大量地使用。
例如:val s = sum(1 to 5 : _*) 通过
:_*
转换成参数序列
案例: 使用递归函数实现累加,如下:
def sum2(nums: Int*): Int = {
if (nums.length == 0) 0
else nums.head + sum2(nums.tail: _*)
}
调用:sum2(1,2,3,4,5) 或是 sum2(1 to 5 :_*)
注:1、定义nums为一个变长参数,定义函数时用*,调用函数需要表示一个参数序列时用:_*
2、head 表示集合中的第一个元素,tail 表示集合中除了第一个元素外的其他元
素
七、过程
定义:在Scala中, 定义函数时, 如果函数体直接包裹在了花括号里面, 而没有使用=连接,
则函数的返回值类型就是Unit, 这样的函数就被称之为过程。过程通常用于不需要返回值的函数。
过程还有一种写法, 就是将函数的返回值类型定义为Unit。比较如下:
def sayHello(name: String) = "Hello, " + name
def sayHello(name: String) { print("Hello, " + name); "Hello, " + name }
def sayHello(name: String): Unit = "Hello, " + name
八、lazy值
在Scala中, 提供了lazy值的特性, 也就是说, 如果将一个变量声明为lazy, 则只有在第一次使用
该变量时, 变量对应的表达式才会发生计算。这种特性对于特别耗时的计算操作特别有用, 比如打开文件进行IO, 进行网络IO等。
1、import scala.io.Source._
lazy val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString
即使文件不存在, 也不会报错, 只有第一次使用变量时会报错, 证明了表达式计算的lazy特性
val lines = fromFile("C://Users//Administrator//Desktop//test.txt").mkString 这句会报错
2、val lines=sc.textFile("file:///home/tg/datas/ws")
val rdd1=lines.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_)
val rdd2=rdd1.collect
算子: flatMap() map() reduceByKey()转换类型的算子(transformation)
collect()行动类型的算子(action)
3、val rdd=lines.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_).map(m=>(m._2,m._1))
.sortByKey(true).map(m=>(m._2,m._1)).collect
注:转换类型的算子就是lazy类型,当遇到action行动类型的算子时,才会触发执行。
总结下划线的用法:
1、导包时,导入包中所有内容 import scala.io.Source._
2、将数列(集合)转换成参数序列 val result=sum(1 to 10:_*)
3、表示Spark算子操作的每一个元素 lines.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_)
八、异常
在Scala中, 异常处理和捕获机制与Java是非常相似的。
try {
throw new IllegalArgumentException("x should not be negative")
} catch {
case _:
IllegalArgumentException => println("Illegal Argument!")
} finally {
print("release resources!")
}
try {
throw new IOException("user defined exception")
} catch {
case e1:
IllegalArgumentException => println("illegal argument")
case e2:
IOException => println("io exception")
}
九、数组
若数组长度固定使用Array,若数组长度不固定则使用ArrayBuffer
1、定长数组的两种创建方式
1》val nums=new Array[Int](10); //10个整数的数组 2》val array=Array("hello","jack")
省略关键字new创建数组的方式,实际上调用的是 Array.scala中的apply()方法。源码如下:
def apply[T: ClassTag](xs: T*): Array[T] = {
val array = new Array[T](xs.length)
var i = 0
for (x <- xs.iterator) {
array(i) = x;
i += 1 }
array}
2、变长数组:数组缓冲
注:scala.collection.mutable._ 可变 scala.collection.immutable._ 不可变
对于那种长度按需要变化的数组,Java有ArrayList,Scala有ArrayBuffer
变长数组ArrayBuffer使用时要导包 import scala.collection.mutable.ArrayBuffer
var arr1=ArrayBuffer[Int]()
变长数组操作:1、arr1+=1 2、arr1+=(2,5,6) 3、arr1 ++=Array(3,4)
4、arr1.trimEnd(5) 返回值为空,需再次调用arr1来查看删除后的数据
5、arr1.insert(1,3,4) 指定1的位置添加3,4元素
6、arr1.remove(3)
7、arr1.remove(3,2) 指定位置删除指定数量的元素
3、变长数组与定长数组之间的转换
变长数组→定长数组:.toArray (不改变原来的数组,系统会自动创建一个新的arry)
定长数组→变长数组:.toBuffer
4、遍历数组
until是RichInt类的方法, 返回所有小于( 不包括) 上限的数字。
5、数组常用算法
,除了sum求和,max最大值,min最小值以外还有如下:
6、数组的quickSort()快速排序方法
scala.util.Sorting.quickSort(array)
十、
高阶函数
filter :把一个函数作为参数的函数
for(i <- 0 until arr1.length if(arr1(i)%2==0)) print(arr1(i)+" ")
array.filter(m=>m%2==0) 这里的m可以省去简写成 array.filter(_%2==0)
m=>m%2==0 匿名函数 m=>{m%2==0}
算子: spark中的算子有一部分是和scala中的高阶函数是一致的,
但是有一部分是scala中没有的,比如reducekey
简写用下划线代替m: val rdd=lines.flatMap(_.split(" ")).map((_,1)).reduceByKey(_+_)
lines.flatMap(m=>m.split(" ")).map(word=>(word,1)).reduceByKey((x,y)=>x+y)
十一、
映射(Map)
1、Scala映射就是键值对的集合Map。默认情况下,Scala中使用不可变的映射。
如果想使用可变集合Map,必须导入scala.collection.mutable.Map
不可变:
val map=Map("tom"->20,"jack"->23,"marray"->22)
val map2=Map(("tom",20),("jack",23),("marray",22))
可变:
val map3=scala.collection.mutable.Map(("tom",20),("jack",23),("marray",22))
val map4=new scala.collection.mutable.HashMap[String,Int]
映射这种数据结构是一种将键映射到值的函数。 区别在于通常的函数计算值, 而映射只是做查询。
2、获取映射中的值
注:1》如果映射并不包含请求中使用的键, 则会抛出异常。
2》要检查映射中是否有某个指定的键, 可以用contains方法。
3》getOrElse方法, 若包含相应的键, 就返回这个键所对应的值, 否则返加0。
4》映射.get(键)这样的调用返回一个Option对象, 要么是Some(键对应的值), 要么是None。
3、修改Map的元素
更新可变Map集合:
1》更新Map的元素 ages("Leo") = 31
2》增加多个元素 ages += ("Mike" -> 35, "Tom" -> 40)
3》 移除元素 ages -= "Mike"
更新不可变Map集合:
1》 添加不可变Map的元素, 产生一个新的集合Map, 原Map不变
val ages2 = ages + ("Mike" -> 36, "Tom" -> 40)
2》移除不可变Map的元素, 产生一个新的集合Map, 原Map不变
val ages3 = ages - "Tom"
4、遍历Map操作
//遍历map的entrySet for ((key, value) <- ages) println(key + " " + value)
// 遍历map的key for (key <- ages.keySet) println(key)
// 遍历map的value for (value <- ages.values) println(value)
// 生成新map, 反转key和value for ((key, value) <- ages) yield (value, key)
5、SortedMap和LinkedHashMap
// SortedMap可以自动对Map的key的排序
val ages = scala.collection.immutable.SortedMap("leo" -> 30, "alice" -> 15, "jen" -> 25)
// LinkedHashMap可以记住插入entry的顺序
val ages = new scala.collection.mutable.LinkedHashMap[String, Int]
ages("leo") = 30
ages("alice") = 15
ages("jen") = 25
6、Java Map与Scala Map的隐式转换
import scala.collection.JavaConversions.mapAsScalaMap
val javaScores = new java.util.HashMap[String, Int]()
javaScores.put("Alice", 10)
javaScores.put("Bob", 3)
javaScores.put("Cindy", 8)
val scalaScores: scala.collection.mutable.Map[String, Int] = javaScores
===========================================================
import scala.collection.JavaConversions.mapAsJavaMap
import java.awt.font.TextAttribute._
val scalaAttrMap = Map(FAMILY -> "Serif", SIZE -> 12)
val fOnt= new java.awt.Font(scalaAttrMap)
7、元组(tuple)
概念:元组是不同类型的值的聚集,对偶是元组的最简单形态,元组的索引从1开始,而不是0
Tuple拉链操作:
Tuple拉链操作指的就是zip操作,zip操作是Array类的方法, 用于将两个Array, 合并为一个Array
比如 Array(v1)和Array(v2), 使用zip操作合并后的格式为Array((v1,v2)),合并后的Array的元素类型为Tuple。例子如下:
val students = Array("Leo", "Jack", "Jen")
val scores = Array(80, 100, 90)
val studentScores = students.zip(scores)
for ((student, score) <- studentScores) println(student + " " + score)
注:如果Array的元素类型是Tuple, 调用Array的toMap方法, 可以将Array转换为Map
如,studentScores.toMap
scala
eval
io
int
编译
jvm
string
spark
byte
写下你的评论吧 !
吐个槽吧,看都看了
会员登录
|
用户注册
推荐阅读
text
SQLite数据库CRUD操作实例分析与应用
本文通过分析和实例演示了SQLite数据库中的CRUD(创建、读取、更新和删除)操作,详细介绍了如何在Java环境中使用Person实体类进行数据库操作。文章首先阐述了SQLite数据库的基本概念及其在移动应用开发中的重要性,然后通过具体的代码示例,逐步展示了如何实现对Person实体类的增删改查功能。此外,还讨论了常见错误及其解决方法,为开发者提供了实用的参考和指导。 ...
[详细]
蜡笔小新 2024-11-05 16:56:48
int
Java 曾经有过配对类吗?—— 探讨 Java 中 Pair 类的历史与现状
本文探讨了 Java 中 Pair 类的历史与现状。虽然 Java 标准库中没有内置的 Pair 类,但社区和第三方库提供了多种实现方式,如 Apache Commons 的 Pair 类和 JavaFX 的 javafx.util.Pair 类。这些实现为需要处理成对数据的开发者提供了便利。此外,文章还讨论了为何标准库未包含 Pair 类的原因,以及在现代 Java 开发中使用 Pair 类的最佳实践。 ...
[详细]
蜡笔小新 2024-11-06 18:56:35
text
探索偶数次幂二项式系数的求和方法及其数学意义
探索偶数次幂二项式系数的求和方法及其数学意义 ...
[详细]
蜡笔小新 2024-11-05 15:38:39
filter
HBase Java API 进阶:过滤器详解与应用实例
本文详细探讨了HBase 1.2.6版本中Java API的高级应用,重点介绍了过滤器的使用方法和实际案例。首先,文章对几种常见的HBase过滤器进行了概述,包括列前缀过滤器(ColumnPrefixFilter)和时间戳过滤器(TimestampsFilter)。此外,还详细讲解了分页过滤器(PageFilter)的实现原理及其在大数据查询中的应用场景。通过具体的代码示例,读者可以更好地理解和掌握这些过滤器的使用技巧,从而提高数据处理的效率和灵活性。 ...
[详细]
蜡笔小新 2024-11-05 15:08:18
text
详解Android连接MySQL数据库的操作流程及技术要点
在Android应用开发中,实现与MySQL数据库的连接是一项重要的技术任务。本文详细介绍了Android连接MySQL数据库的操作流程和技术要点。首先,Android平台提供了SQLiteOpenHelper类作为数据库辅助工具,用于创建或打开数据库。开发者可以通过继承并扩展该类,实现对数据库的初始化和版本管理。此外,文章还探讨了使用第三方库如Retrofit或Volley进行网络请求,以及如何通过JSON格式交换数据,确保与MySQL服务器的高效通信。 ...
[详细]
蜡笔小新 2024-11-07 19:11:13
int
Java面向对象编程核心概念解析与应用
本文深入解析了Java面向对象编程的核心概念及其应用,重点探讨了面向对象的三大特性:封装、继承和多态。封装确保了数据的安全性和代码的可维护性;继承支持代码的重用和扩展;多态则增强了程序的灵活性和可扩展性。通过具体示例,文章详细阐述了这些特性在实际开发中的应用和优势。 ...
[详细]
蜡笔小新 2024-11-07 17:53:00
int
Python编程实现足球联赛赛程安排的策略与简易示例分析
每年,意甲、德甲、英超和西甲等各大足球联赛的赛程表都是球迷们关注的焦点。本文通过 Python 编程实现了一种生成赛程表的方法,该方法基于蛇形环算法。具体而言,将所有球队排列成两列的环形结构,左侧球队对阵右侧球队,首支队伍固定不动,其余队伍按顺时针方向循环移动,从而确保每场比赛不重复。此算法不仅高效,而且易于实现,为赛程安排提供了可靠的解决方案。 ...
[详细]
蜡笔小新 2024-11-07 17:41:40
int
深入理解 Java 控制结构的全面指南
深入理解 Java 控制结构的全面指南 ...
[详细]
蜡笔小新 2024-11-06 16:40:43
text
深入解析 Golang 中 Context 的功能与应用
本文详细探讨了 Golang 中 Context 的核心功能及其应用场景,通过深入解析其工作机制,帮助读者更好地理解和运用这一重要特性,对于提升代码质量和项目开发效率具有重要的参考价值。 ...
[详细]
蜡笔小新 2024-11-06 16:35:57
int
Python 进阶教程:自定义序列类的详细解析与实践
本课程深入探讨了 Python 中自定义序列类的实现方法,涵盖从基础概念到高级技巧的全面解析。通过实例演示,学员将掌握如何创建支持切片操作的自定义序列对象,并了解 `bisect` 模块在序列处理中的应用。适合希望提升 Python 编程技能的中高级开发者。 ...
[详细]
蜡笔小新 2024-11-06 09:08:22
int
Objective-C 中的委托模式详解与应用
Objective-C 中的委托模式详解与应用 ...
[详细]
蜡笔小新 2024-11-07 17:42:20
int
Python内置模块详解:正则表达式re模块的应用与解析
正则表达式是一种强大的文本处理工具,通过特定的字符序列来定义搜索模式。本文详细介绍了Python内置的`re`模块,探讨了其在字符串匹配、验证和提取中的应用。例如,可以通过正则表达式验证电子邮件地址、电话号码、QQ号、密码、URL和IP地址等。此外,文章还深入解析了`re`模块的各种函数和方法,提供了丰富的示例代码,帮助读者更好地理解和使用这一工具。 ...
[详细]
蜡笔小新 2024-11-07 17:25:01
int
手指触控|Android电容屏幕驱动调试指南
手指触控|Android电容屏幕驱动调试指南 ...
[详细]
蜡笔小新 2024-11-07 01:42:20
int
蓝桥杯物联网基础教程:通过GPIO输入控制LED5的点亮与熄灭
本教程详细介绍了如何利用STM32的GPIO接口通过输入信号控制LED5的点亮与熄灭。内容涵盖GPIO的基本配置、按键检测及LED驱动方法,适合具有STM32基础的读者学习和实践。 ...
[详细]
蜡笔小新 2024-11-06 14:39:27
text
动态壁纸 LiveWallPaper:让您的桌面栩栩如生(第二篇)
在本文中,我们将继续探讨如何开发动态壁纸 LiveWallPaper,使您的桌面更加生动有趣。作为 2010 年 Google 暑期大学生博客分享大赛 Android 篇的一部分,我们将详细介绍 Ed Burnette 的《Hello, Android》第三版中的相关内容,并分享一些实用的开发技巧和经验。通过本篇文章,您将了解到如何利用 Android SDK 创建引人入胜的动态壁纸,提升用户体验。 ...
[详细]
蜡笔小新 2024-11-06 02:00:32
爱与嫉妒咋
这个家伙很懒,什么也没留下!
Tags | 热门标签
rsa
utf-8
match
emoji
ascii
testing
controller
lua
header
usb
bytecode
c语言
range
js
stream
dockerfile
int
plugins
less
blob
merge
filter
node.js
jar
hashtable
cSharp
tree
process
text
php7
RankList | 热门文章
1
AlienVerse 忠诚度计划上线!
2
红手指如何使用?红手指使用方法
3
Spring声明式事务不回滚问题
4
WinForm打包后皮肤无效(解决方案)
5
selenium的三种等待的区别
6
用法_java if else 用法
7
MFC中使用用户剪贴板
8
PHP RSS类的使用方法及在4G中主要使用的技术:如何在PHP中使用RSS技术
9
如何合并磁盘分区?附操作技巧
10
扩大微信小顺序 Page 组织函数,修正性命周期函数
11
转 class和struct最本质的区别
12
AFNetworking、MKNetworkKit和ASIHTTPRequest比较
13
令妃刚生完孩子,为什么乾隆就要她侍寝?
14
webpack dev server运行发生错误
15
免费手机铃声 免费手机铃声在线下载
PHP1.CN | 中国最专业的PHP中文社区 |
DevBox开发工具箱
|
json解析格式化
|
PHP资讯
|
PHP教程
|
数据库技术
|
服务器技术
|
前端开发技术
|
PHP框架
|
开发工具
|
在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved |
京公网安备 11010802041100号
|
京ICP备19059560号-4
| PHP1.CN 第一PHP社区 版权所有