Swift3.0学习笔记-Collection Types

https://developer.apple.com/library/prerelease/content/documentation/Swift/Conceptual/Swift_Programming_Language/CollectionTypes.html#//apple_ref/doc/uid/TP40014097-CH8-ID105


        Swift提供3种集合类型, 包含数组Array、集合Set和字典Dictionary, 功能类似于Java的ArrayList、HashSet和HashMap。Array数组是地址连续且有序的值, Set是地址不连续且存储的值唯一,字典Dictionary存储了一些key-value。 PS:有Java基础的很好理解。

                     

       Array、Set和Dictionary存储的数据必须是约定的数据类型,   不能插入其它数据类型,  所以从集合中取出的数据肯定是同一个数据类型。


集合的可修改性:

      实例化一个Array、Set或者Dictionary后, 你可以增删改查其中的数据(使用var关键字)。 但是当你将集合声明为常量时(即使用let关键字), 集合的数据不可修改。


数组Array:

       在连续地址空间存储类型相同的值,同一个值可以出现多次。Swift的Array可直接操作Object-C的NSString对象。 通过2种方式创建Array, 即 Array<T> 或者 [T] 。 T是数组元素的类型, 在这里是泛型。(跟Java的ArrayList一样使用泛型)

    

创建空数组:

    var someInts = [Int]()       //somInts是Int型数组
    print("someInts is of type [Int] with \(someInts.count) items.")
    // 输出"someInts is of type [Int] with 0 items."
<pre name="code" class="java">  someInts.append(3)     //在数组末尾插入数字3, 看着像Java的StringBuilder/StringBuffer用法
    // someInts数组含有1个数据3
    someInts = []  // someInts 变为空数组, 仍然是整型数组[Int]。 类似于Java的clear方法
 

     
 

使用默认值创建数组:

        Swift支持创建具有默认值的数组,  即在实例化数组时对其中的元素赋值。 第一个参数repeating是参数值(根据值确定其数据类型), 第二个参数是数组个数。

    var threeDoubles = Array(repeating: 0.0, count: 3)
    // threeDoubles是个[Double]数组, 包含3个相同值即[0.0, 0.0, 0.0]
    功能类似于C++语言的

double[] threeDouble = new double[3];
memset(threeDouble, 0, sizeof(threeDouble));     

数组拼接(类似于String的拼接)

    var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
    // anotherThreeDoubles是[Double]数组, 值是 [2.5, 2.5, 2.5]
    var sixDoubles = threeDoubles + anotherThreeDoubles
    // sixDoubles也是[Double]数组, 值等于2个数组的并集即 [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]


使用数组标识符[]创建数组(类似于使用Java的{}创建数组)

var shoppingList: [String] = ["Eggs", "Milk"]   //shoppingList是String数组,包含Eggs和Milk
<code class="code-voice"><span class="kt">var</span> <span class="vc">shoppingList</span> = [<span class="s">"Eggs"</span>, <span class="s">"Milk"</span>]</code>   //Swift语法中可以省略类型参数,而且跟上面语句的功能完全一致! <strong><span style="color:#FF0000;">前提是数组内容的数据类型必须都相同</span></strong>
等同于Java的

String[] shoppingList = {"Eggs", "Milk"};


读取和修改Array数据:

print("The shopping list contains \(shoppingList.count) items.")
// 输出"The shopping list contains 2 items.", 使用成员变量count得到数组元素个数
<pre name="code" class="java">if shoppingList.isEmpty {  //使用isEmpty属性判断数组是否为空, 即包含0个元素
    print("The shopping list is empty.")
} else {
    print("The shopping list is not empty.")  //因为数组里有2个元素、非空,所以isEmpty等于false
}
// Prints "The shopping list is not empty."  
shoppingList.append("Flour")       //使用append方法向数组里添加元素
shoppingList += ["Baking Powder"]    //前面已经提到了,2个数组之间用+号分隔表示数组拼接。
// shoppingList包含4条数据
shoppingList += ["Chocolate Spread", "Cheese", "Butter"]  //再添加3条后,count等于7
<pre name="code" class="java">var firstItem = shoppingList[0]  //数组是连续地址空间,可以通过下标得到对应数据,下标范围[0,count),
跟其它语言一样。

<pre name="code" class="java">shoppingList[4...6] = ["Bananas", "Apples"]  //批量替换数组中的元素4...6表示4、5和6,即3个元素。
等同于
shoppingList[4] = "Bannanas"
shoppingList[5] = "Apples"
因为左边4/5/6等3个下标需要修改值, 但右侧只有2个值Bannans/Apples, 下标6缺少对应的值;在Swift语言中遇到
这种情况时会删除下标6的元素, 即shoppingList数组长度减1, 从7变为6。
PS:这个语法在内存优化方面很有用, 一句话就删除了数组冗余的空间。 想想Java是怎么做的? 新创建个小数组,
将大数组中有用的值拷进来, 然后删除大数组的引用。

 
 

 

如果想在数组某个位置插入一条数据时, Swift提供了insert(_:at:)方法。 比如:

  shoppingList.insert("Maple Syrup", at: 0)
 // shoppingList数组在下标0即首部插入一条数据, 共包含7条数据。 而且"Maple Syrup"是下标0即第一条数据
PS:你只要知道insert方法, XCode会提示用法的。

那如何删除数组元素呢? Swift提供了remove方法, 我觉得猜也能猜到吐舌头 无非是remove或者delete。

let mapleSyrup = shoppingList.remove(at: 0)  //同insert用法, 删除指定下标的数据, 数组长度减1
//“Maple Syrup”这条数据被删除了, 数组长度变为6


遍历数组(Swift提供了跟Java类似的for-in语法)

for item in shoppingList {   //item是String类型
    print(item)    
}
或者通过下标做循环
var i = 0
while i < shoppingList.count {
    print(shoppingList[i])
    i += 1
}

对于Array中的每个元素, enumerated()方法可以返回其对应的键值对(index, value),即(下标,  值)。

for (index, value) in shoppingList.enumerated() { //index是Int型下标,value跟数组元素数据类型相同
 print("Item \(index + 1): \(value)")
}
输出:
// Item 1: Six eggs
// Item 2: Milk
// Item 3: Flour
// Item 4: Baking Powder
// Item 5: Bananas

小结: Swift的Array数组跟Java的类似,   但新增了几个语法。 比如批量替换数据很牛X, 因为它还能缩短数组长度!!! 要知道Java为了避免数组空间浪费, 还弄了个稀疏矩阵SparseArray解决这个问题。



Set语法(跟Java类似,很好理解。 跟Array的区别就是Set里的数据都是唯一的、跟其它数据不一样)

var letters = Set<Character>()     //声明一个字符型集合, 是空的哦!  
print("letters is of type Set<Character> with \(letters.count) items.")
// 输出"letters is of type Set<Character> with 0 items."

Set类型也可以像Array那样插值和置空

letters.insert("a")    //插入第一个数据, 注意用的是双引号!
letters = []      //letters变为空, 数据类型不变, 仍然是Set<Character>


跟初始化Array类型, Set也可以赋初值。

var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres集合包含3条记录, 记录都是String类型

回想上面数组的定义方式, Swift语言可以通过记录类型确定集合的类型, 所以还可以这样写

var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]  //Set后面没有数据类型, 但它仍然等同于Set<String>


跟Array一样的判空方式, 如:

if favoriteGenres.isEmpty {   //favoriteGenres包含3个记录, isEmpty为false
    print("As far as music goes, I'm not picky.")
} else {
    print("I have particular music preferences.")
}
// 输出"I have particular music preferences."

favoriteGenres.insert("Jazz")   //非常熟悉的insert方法,即插入数据


Set提供了remove和removeAll方法。 顾名思义remove是删除一条记录,如果在Set中则返回值是要删除的数据;如果不在Set中则返回nil。 removeAll是清空Set,删除所有记录。
if let removedGenre = favoriteGenres.remove("Rock") {  //注意这里的语法,removedGenre常量只是为了下面打印语句使用, 也可以写成 if favoriteGenres.remove("Rock") { 。 如果值为nil则进入else分支, 值不是nil则进入if分支。
    print("\(removedGenre)? I'm over it.")  
} else {
    print("I never much cared for that.")
}
// 输出 "Rock? I'm over it."

如果想判断Set里是否包含某元素,如何做? 第一反应肯定是contains方法, Swift也是这么干的, 这点跟Java相同。

if favoriteGenres.contains("Funk") {   //判断favoriteGenres里是否含有Funk, 有则为true,无则为false。
    print("I get up on the good foot.")
} else {
    print("It's too funky in here.")
}
// 输出"It's too funky in here."

Set跟Array一样使用for-in循环遍历:

for genre in favoriteGenres {
    print("\(genre)")
}


Set还提供了4个集合方法:假设a和b都是Set集合。

intersection(交集):  a.intersection(b) 会得到二者交集;

symmetricDifference(相加并删除相同部分): a.symmetricDifference(b)会得到二者相加且删掉相同部分后的集合。

union(并集): a.union(b)会得到二者的全部;

subtracting(删掉相同部分): a.subtracting(b)会得到删除与b相同部分后的a。


小结: Set跟Array的API很相似, 区别是Array可以操作指定位置的数据, 而Set做不到。



Dictionary字典:

       Dictionary可以调用Object-C的NSDictionary, 包含的数据是key-value键值对, 跟HashMap功能一样。 key的数据类型都一样, value的数据类型都一样。


var namesOfIntegers = [Int: String]()    //创建一个空Dictionary, 语法有点像Array。 key是Int型, value是String型。

namesOfIntegers[16] = "sixteen"
// namesOfIntegers有1个键值对了, 即(16, "sixteen")
namesOfIntegers = [:]      //空Dictionary, 数据类型不变; 想想清空Array怎么做的? 是[] , 区分是有无冒号。
// namesOfIntegers数据类型不变,仍然是Dictionary的 [Int: String]、


跟初始化Array类型, 初始化Dictionary就是多了冒号。

var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]  

//airports是Dictionary<String,String>类型, 包含2个键值对


就像Set一样, 在声明Dictionary时不必写数据类型, Swift会根据值判断数据类型。

var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]    //省略了[String: String]但功能一样

  1. airports["LHR"] = "London" //airports里key没有"LHR", 在这里会新插入一条数据, airports包含3条键值对
  2. airports["LHR"] = "BeiJing" //airports里key存在"LHR", 在这里会更新对应的value。 airports仍然是3条键值对
  3. 说明:对于Dictionary, =可能是插入或者更新功能, 取决于Dictionary里是否存在相同key。

Swift还提供了updateValue(_:forKey:) 方法用于插入或者更新键值对, 跟=功能类似, 区别是updateValue会返回当前key对应的value, 如果Dictionary没有对应的key则是新增、跟=功能完全一样; 如果存在相同的key, 那么就是更新其键值并返回当前旧值, 这是=号做不到的。

     所以可以通过判断updateValue返回值是否nil, 判断是插入或者更新。

if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
    print("The old value for DUB was \(oldValue).")
}

// 因为Dictionary里存在"Dub“的key, 所以是更新操作,函数返回“Dublin“,不是nil。 if为true, 所以输出"The old value for DUB was Dublin."


 Dictionary跟Java的HashMap一样,也是通过key寻址删除键值对。 Swift提供了removeValue(forKey:_)函数, 找到键值对后会返回value并删除该键值对, 否则返回nil。

if let removedValue = airports.removeValue(forKey: "DUB") {
    print("The removed airport's name is \(removedValue).")
} else {
    print("The airports dictionary does not contain a value for DUB.")
}
// 输出"The removed airport's name is Dublin Airport."


遍历, 语法跟Array一样的for-in

  遍历键值对:

for (airportCode, airportName) in airports {
    print("\(airportCode): \(airportName)") 
}
遍历键:

for airportCode in airports.keys {
    print("Airport code: \(airportCode)")
}
遍历值:

  1. for airportName in airports.values {
        print("Airport name: \(airportName)")
    }

  2. 说明: Java的HashMap只能遍历key, 因为有个缓存key的Set; 但没提供遍历value的方法; Dictionary能遍历键值对、键、值, API比Java更强大。


Dictionary还能拿到键、值的数组, 语法如下:
let airportCodes = [String](airports.keys)
// airportCodes 是["YYZ", "LHR"]
 
let airportNames = [String](airports.values)
// airportNames 是 ["Toronto Pearson", "London Heathrow"]

小结: Dictionary比Java的HashMap功能更强大, 尤其是在遍历功能上做的很完善。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值