1. Dictionary
和java中的Map类似,可以用来存放键值对。
说明
必须包含名空间System.Collection.Generic
Dictionary里面的每一个元素都是一个键值对(由二个元素组成:键和值)
键必须是唯一的,而值不需要唯一的
键和值都可以是任何类型(比如:string, int, 自定义类型,等等)
通过一个键读取一个值的时间是接近O(1)
键值对之间的偏序可以不定义
-
创建及初始化
Dictionary<int,string>myDictionary=newDictionary<int,string>();
-
添加元素
myDictionary.Add(1,"C#");
myDictionary.Add(2,"C++");
myDictionary.Add(3,"ASP.NET");
myDictionary.Add(4,"MVC");
-
通过Key查找元素
if(myDictionary.ContainsKey(1))
{
Console.WriteLine("Key:{0},Value:{1}","1", myDictionary[1]);
}
-
通过KeyValuePair遍历元素
foreach(KeyValuePair<int,string>kvp in myDictionary)
...{
Console.WriteLine("Key = {0}, Value = {1}",kvp.Key, kvp.Value);
}
-
仅遍历键 Keys 属性
Dictionary<int,string>.KeyCollection keyCol=myDictionary.Keys;
foreach(intkeyinkeyCol)
...{
Console.WriteLine("Key = {0}", key);
}
-
仅遍历值 Valus属性
Dictionary<int,string>.ValueCollection valueCol=myDictionary.Values;
foreach(stringvalueinvalueCol)
...{
Console.WriteLine("Value = {0}", value);
}
-
通过Remove方法移除指定的键值
myDictionary.Remove(1);
if(myDictionary.ContainsKey(1))
...{
Console.WriteLine("Key:{0},Value:{1}","1", myDictionary[1]);
}
else
{
Console.WriteLine("不存在 Key : 1");
}
下面是我自己的例子:
2. 正则表达式/HTML图片显示/Select下拉框
2.1 正则表达式
正则表达式,又称规则表达式,英文名为Regular Expression,在代码中常简写为regex、regexp或RE,是计算机科学的一个概念。正则表通常被用来检索、替换那些符合某个模式(规则)的文本。
正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,模式描述在搜索文本时要匹配的一个或多个字符串。
上图为控制输入框的内容不能为汉字的正则表达式。每个符号所代表的意思如下:
2.2 HTML图片显示
在使用<img>标签显示图片时,如果图片太大显示会超出div的大小。这回导致页面可以横向滑动,但是没有图片的地方div大小正常,被图片撑大的部分显示的就是上一个页面的内容。
水平方向撑开的解决方法就是添加style=”display:block;width:100%。其中,display:block;此元素将显示为块级元素,此元素前后会带有换行符。width:100%,将宽度设为100%,这个块级元素宽度就被固定了。该元素不会被撑开,而是按比例缩小显示。
如果加入图片较小能在一个页面显示可以按照水平方向的解决方法加上height:100%解决,但是如果图片较大,需要下拉。可以在页面加一个滚动条style="overflow-y: scroll;"原本未加滚动条时,因为图片大将<img>元素撑大,不在所框住的div内,也能下拉,但是能看到上一页面的未覆盖的内容。加了y方向的滚动条后就能解决这一问题。
2.3 Select下拉框
在 HTML 表单中,<select> 标签每出现一次,一个 Select 对象就会被创建。在使用选择框时,如需要默认初始值,添加selected = 'selected'; 属性,该选项即为默认选项。
将初始val赋为空,这样“请选择”项的val即为空,世纪选项就没有“请选择”项了。
源码:
<input type="text" class="uc-a1" style="border: none;font-size:
0.8125em;"id="RelaCredNo"onkeyup="value=value.replace(/[^\w\.\/]/ig,'')">
<div class="bc-bg" tabindex="0" data-control="PAGE" id="Page" style="overflow-y: scroll">
$("#show_img").append('<img src="'+relaImage+'" style="display:block;width:100%">');
var result = JSON.parse(appcan.locStorage.getVal("selectRelaType"));
var str = "";
str += "<option value='' selected = 'selected'>请选择</option>";
if (result.indexOf("本人|") < 0) {
str += "<option value='1'>本人</option>";
}
if (result.indexOf("父亲|") < 0) {
str += "<option value='2'>父亲</option>";
}
if (result.indexOf("母亲|") < 0) {
str += "<option value='3'>母亲</option>";
}
if (result.indexOf("配偶父|") < 0) {
str += "<option value='4'>配偶父</option>";
}
if (result.indexOf("配偶母|") < 0) {
str += "<option value='5'>配偶母</option>";
}
if (result.indexOf("配偶|") < 0) {
str += "<option value='6'>配偶</option>";
}
str += "<option value='7'>子女</option>";
$("#RelaType").append(str);
$('#RelaType').val("");
$("#RelaCredType").append("<option value='' selected = 'selected'>请选择</option>
<option value='1'>身份证</option><option value='2'>护照</option>");
$('#RelaCredType').val("");
3. 容器介绍
3.1 Array/ArrayList/List/LinkedList
-
Array
数组在C#中最早出现的。在内存中是连续存储的,所以它的索引速度非常快,而且赋值与修改元素也很简单。
1. string[] s=new string[2];
2.
3. //赋值
4. s[0]="a";
5. s[1]="b";
6. //修改
7. s[1]="a1";
但是数组存在一些不足的地方。在数组的两个数据间插入数据是很麻烦的,而且在声明数组的时候必须指定数组的长度,数组的长度过长,会造成内存浪费,过短会造成数据溢出的错误。如果在声明数组时我们不清楚数组的长度,就会变得很麻烦。
针对数组的这些缺点,C#中最先提供了ArrayList对象来克服这些缺点。
底层数据结构就是数组。
-
ArrayList
ArrayList是命名空间System.Collections下的一部分,在使用该类时必须进行引用,同时继承了IList接口,提供了数据存储和检索。ArrayList对象的大小是按照其中存储的数据来动态扩充与收缩的。所以,在声明ArrayList对象时并不需要指定它的长度。
1. ArrayList list1 = new ArrayList();
2.
3. //新增数据
4. list1.Add("cde");
5. list1.Add(5678);
6.
7. //修改数据
8. list[2] = 34;
9.
10. //移除数据
11. list.RemoveAt(0);
12.
13. //插入数据
14. list.Insert(0, "qwe");
从上面例子看,ArrayList好像是解决了数组中所有的缺点,为什么又会有List?
我们从上面的例子看,在List中,我们不仅插入了字符串cde,而且插入了数字5678。这样在ArrayList中插入不同类型的数据是允许的。因为ArrayList会把所有插入其中的数据当作为object类型来处理,在我们使用ArrayList处理数据时,很可能会报类型不匹配的错误,也就是ArrayList不是类型安全的。在存储或检索值类型时通常发生装箱和取消装箱操作,带来很大的性能耗损。
装箱与拆箱的概念:
装箱:就是将值类型的数据打包到引用类型的实例中比如将string类型的值abc赋给object对象obj
1. String i=”abc”;
2. object obj=(object)i;
拆箱:就是从引用数据中提取值类型
比如将object对象obj的值赋给string类型的变量i。
1. object obj=”abc”;
2. string i=(string)obj;
装箱与拆箱的过程是很损耗性能的。
底层数据结构就是数组。类似于C++里面没有泛型的Vector。
-
泛型List
因为ArrayList存在不安全类型与装箱拆箱的缺点,所以出现了泛型的概念。List类是ArrayList类的泛型等效类,它的大部分用法都与ArrayList相似,因为List类也继承了IList接口。最关键的区别在于,在声明List集合时,我们同时需要为其声明List集合内数据的对象类型。
比如:
1. List<string> list = new List<string>();
2. //新增数据
3. list.Add(“abc”);
4. //修改数据
5. list[0] = “def”;
6. //移除数据
7. list.RemoveAt(0);
上例中,如果我们往List集合中插入int数组123,IDE就会报错,且不能通过编译。这样就避免了前面讲的类型安全问题与装箱拆箱的性能问题了。
底层数据结构就是数组。类似于C++里面的Vector。
-
LinkedList
用双链表实现的List,特点是插入删除快,查找慢
LinkedList<T> 提供 LinkedListNode<T> 类型的单独节点,因此插入和移除的运算复杂度为 O(1)。
可以移除节点,然后在同一列表或其他列表中重新插入它们,这样在堆中便不会分配额外的对象。由于该列表还维护内部计数,因此获取 Count 属性的运算复杂度为 O(1)。
LinkedList<T> 对象中的每个节点都属于 LinkedListNode<T> 类型。由于 LinkedList<T> 是双向链表,因此每个节点向前指向 Next 节点,向后指向 Previous 节点。
1. LinkedList<string> list = new LinkedList<string>();
2. list.AddFirst("Data Value 1");
3. list.AddLast("Data Value 6");
关于List和LonkedList的一个性能比较
-
增加 删除
在List<T>中增加、删除节点的速度,大体上快于使用LinkedList<T>时的相同操作。将 List<T>.Add方法和LinkedList<T>的Add*方法相比较,真正的性能差别不在于Add操作,而在LinkedList<T>在给GC(垃圾回收机制)的压力上。一个List<T>本质上是将其数据保存在一个堆栈的数组上,而LinkedList<T>是将其所有节点保存在堆栈上(人家是一个,我是一系列)。这就使得GC需要更多地管理堆栈上LinkedList<T>的节点对象。注意,List<T>.Insert方法比在LinkedList<T>中使用Add方法在任何地方添加一个节点可能要慢。然而,这个依赖于List<T>插入对象的位置。Insert方法必须使所有在插入点后面的元素往后移动一位。如果新元素被插在List<T>最后或接近最后的位置,那么相对于GC维护LinkedList<T>节点的总的开销来说,其开销是可以被忽略的。
-
索引
另一个List<T>性能优于LinkedList<T>的地方是你在使用索引进行访问的时候。在List<T>中,你可以使用索引值(indexer)直接定位到某个具体的元素位置。而在LinkedList<T>中,却没有这样的奢侈品。在LinkedList<T>中,你必须通过Previous或Next属性遍历整个List,直到找到你想要的节点。
3.2 HashSet/HashTable/Dictionary
这三个容器的底层都是Hash表。
-
HashSet
MSDN很简单的解释:表示值的集。
HashSet<T> 类提供了高性能的集运算。一组是一个集合,不包含任何重复的元素,且的元素顺序不分先后。
用了hash table来储存数据,是为了用O(n)的space来换取O(n)的时间,也就是查找元素的时间是O(1)。
它包含一些集合的运算
HashSet<T> 提供了许多数学设置操作例如,组添加 (联合),并设置减法。下表列出了所提供 HashSet<T> 操作和及其数学等效项。
UnionWith - Union 或将其设置的添加
IntersectWith - 交集
ExceptWith - Set 减法
SymmetricExceptWith - 余集
列出的集操作中,除了 HashSet<T> 类还提供了方法来确定 set 是否相等、 重叠的集,以及一组是否为子集或另一个集的超集。
example
1. HashSet<int> evenNumbers = new HashSet<int>();
2. HashSet<int> oddNumbers = new HashSet<int>();
3.
4. for (int i = 0; i < 5; i++)
5. {
6. // Populate numbers with just even numbers.
7. evenNumbers.Add(i * 2);
8. // Populate oddNumbers with just odd numbers.
9. oddNumbers.Add((i * 2) + 1);
10. }
11. // Create a new HashSet populated with even numbers.
12. HashSet<int> numbers = new HashSet<int>(evenNumbers);
13. numbers.UnionWith(oddNumbers);
-
HashTable
表示根据键的哈希代码进行组织的键/值对的集合。
Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似key/value的键值对,其中key通常可用来快速查找,同时key是区分大小写;value用于存储对应于key的值。
Hashtable中key/value键值对均为object类型,所以Hashtable可以支持任何类型的key/value键值对.
他内部维护很多对Key-Value键值对,其还有一个类似索引的值叫做散列值(HashCode),它是根据GetHashCode方法对Key通过一定算法获取得到的,所有的查找操作定位操作都是基于散列值来实现找到对应的Key和Value值的
当前HashTable中的被占用空间达到一个百分比的时候就将该空间自动扩容,在.net中这个百分比是72%,也叫.net中HashTable的填充因子为0.72。例如有一个HashTable的空间大小是100,当它需要添加第73个值的时候将会扩容此HashTable.
这个自动扩容的大小是多少呢?答案是当前空间大小的两倍最接近的素数,例如当前HashTable所占空间为素数71,如果扩容,则扩容大小为素数131.
1. Hashtable openWith = new Hashtable();
2.
3. // Add some elements to the hash table. There are no
4. // duplicate keys, but some of the values are duplicates.
5. openWith.Add("txt", "notepad.exe");
6. openWith.Add("bmp", "paint.exe");
7. openWith.Add("dib", "paint.exe");
8. openWith.Add("rtf", "wordpad.exe");
HashTable也有Boxing和Unboxing的开销。
然后就有了
-
Dictionary
Dictionary也是键值容器,存入对象是需要与[key]值一一对应的存入该泛型。相对于HashTable,类似于List和ArrayList的关系。它是类型安全的。
1. Dictionary<string, string> myDic = new Dictionary<string, string>();
2. myDic.Add("aaa", "111");
3. myDic.Add("bbb", "222");
4. myDic.Add("ccc", "333");
5. myDic.Add("ddd", "444");
-
小结
数组的容量是固定的,您只能一次获取或设置一个元素的值,而ArrayList或List<T>的容量可根据需要自动扩充、修改、删除或插入数据。
数组可以具有多个维度,而 ArrayList或 List< T> 始终只具有一个维度。但是,您可以轻松创建数组列表或列表的列表。特定类型(Object 除外)的数组 的性能优于 ArrayList的性能。 这是因为 ArrayList的元素属于 Object 类型;所以在存储或检索值类型时通常发生装箱和取消装箱操作。不过,在不需要重新分配时(即最初的容量十分接近列表的最大容量),List< T> 的性能与同类型的数组十分相近。
在决定使用 List<T> 还是使用ArrayList 类(两者具有类似的功能)时,记住List<T> 类在大多数情况下执行得更好并且是类型安全的。如果对List< T> 类的类型T 使用引用类型,则两个类的行为是完全相同的。但是,如果对类型T使用值类型,则需要考虑实现和装箱问题。
所以基本不怎么用ArrayList.
还要注意的一点
在单线程的时候使用Dictionary更好一些,多线程的时候使用HashTable更好。
因为HashTable可以通过Hashtable tab = Hashtable.Synchronized(new Hashtable());获得线程安全的对象。
网上找的C#学习内容:
HTML---css/div---- SQL----C#----面向对象-----设计模式----MVC----EntityFramework-----C#深入了解-----WebForm-----javascript----jquery----angularJS----.netCore------现在。。。。
往后我可能要继续学习-----架构----深入理解设计模式------.netCore-----NodeJs.------Git-----Docker
还有Unity3D------操作系统-----编译原理-----数据结构等。。。。。。。
4. Python多线程与多线程中join()的用法
Python多线程与多进程中join()方法的效果是相同的。
下面仅以多线程为例:
首先需要明确几个概念:
知识点一:
当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置多线程时,主线程会创建多个子线程,在python中,默认情况下(其实就是setDaemon(False)),主线程执行完自己的任务以后,就退出了,此时子线程会继续执行自己的任务,直到自己的任务结束,例子见下面一。知识点二:
当我们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行,可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止,例子见下面二。知识点三:
此时join的作用就凸显出来了,join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程在终止,例子见下面三。知识点四:
join有一个timeout参数:
- 当设置守护线程时,含义是主线程对于子线程等待timeout的时间将会杀死该子线程,最后退出程序。所以说,如果有10个子线程,全部的等待时间就是每个timeout的累加和。简单的来说,就是给每个子线程一个timeout的时间,让他去执行,时间一到,不管任务有没有完成,直接杀死。
- 没有设置守护线程时,主线程将会等待timeout的累加和这样的一段时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。
4.1 Python多线程的默认情况
import threading
import time
def run():
time.sleep(2)
print('当前线程的名字是: ', threading.current_thread().name)
time.sleep(2)
if __name__ == '__main__':
start_time = time.time()
print('这是主线程:', threading.current_thread().name)
thread_list = []
for i in range(5):
t = threading.Thread(target=run)
thread_list.append(t)
for t in thread_list:
t.start()
print('主线程结束!' , threading.current_thread().name)
print('一共用时:', time.time()-start_time)
其执行结果如下
C:\Users\yuanyizhang\AppData\Local\Programs\Python\Python36-32\python.exe
C:/Users/yuanyizhang/PycharmProjects/untitled/test.py
这是主线程: MainThread
主线程结束! MainThread
一共用时: 0.0020051002502441406
当前线程的名字是: Thread-1
当前线程的名字是: Thread-5
当前线程的名字是: Thread-4
当前线程的名字是: Thread-3
当前线程的名字是: Thread-2
Process finished with exit code 0
关键点:
- 我们的计时是对主线程计时,主线程结束,计时随之结束,打印出主线程的用时。
- 主线程的任务完成之后,主线程随之结束,子线程继续执行自己的任务,直到全部的子线程的任务全部结束,程序结束。
4.2 设置守护线程
import threading
import time
def run():
time.sleep(2)
print('当前线程的名字是: ', threading.current_thread().name)
time.sleep(2)
if __name__ == '__main__':
start_time = time.time()
print('这是主线程:', threading.current_thread().name)
thread_list = []
for i in range(5):
t = threading.Thread(target=run)
thread_list.append(t)
for t in thread_list:
t.setDaemon(True)
t.start()
print('主线程结束了!' , threading.current_thread().name)
print('一共用时:', time.time()-start_time)
其执行结果如下,注意请确保setDaemon()在start()之前。
C:\Users\yuanyizhang\AppData\Local\Programs\Python\Python36-32\python.exe
C:/Users/yuanyizhang/PycharmProjects/untitled/test.py
这是主线程: MainThread
主线程结束了! MainThread
一共用时: 0.0010030269622802734
Process finished with exit code 0
关键点:
- 非常明显的看到,主线程结束以后,子线程还没有来得及执行,整个程序就退出了。
4.3 join的作用
import threading
import time
def run():
time.sleep(2)
print('当前线程的名字是: ', threading.current_thread().name)
time.sleep(2)
if __name__ == '__main__':
start_time = time.time()
print('这是主线程:', threading.current_thread().name)
thread_list = []
for i in range(5):
t = threading.Thread(target=run)
thread_list.append(t)
for t in thread_list:
t.setDaemon(True)
t.start()
for t in thread_list:
t.join()
print('主线程结束了!' , threading.current_thread().name)
print('一共用时:', time.time()-start_time)
其执行结果如下:
这是主线程: MainThread
当前线程的名字是: Thread-1
当前线程的名字是: Thread-2
当前线程的名字是: Thread-4
当前线程的名字是: Thread-5
当前线程的名字是: Thread-3
主线程结束了! MainThread
一共用时: 4.004054546356201
关键点:
- 可以看到,主线程一直等待全部的子线程结束之后,主线程自身才结束,程序退出。
- 可以通过join(time)设置时间 控制主线程是否等待子线程结束再结束,设置时间较小时,等待时间不足,主线程会先结束(本例可设置join(0.3)),时间足够长时,主线程等待足够时间,子线程可以全部结束(本例设置join(1))
5. Flex布局
flex 做布局太容易了,尤其是在垂直居中这方面
布局的传统解决方案,基于盒状模型,依赖 display 属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。
Flex 是 Flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。
任何一个容器都可以指定为 Flex 布局。
.box{
display: flex;
}
行内元素也可以使用 Flex 布局。
.box{
display: inline-flex;
}
Webkit 内核的浏览器,必须加上-webkit前缀。
注意,设为 Flex 布局以后,子元素的float、clear和vertical-align属性将失效。
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。
项目默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。
容器的属性
以下6个属性设置在容器上。
flex-direction
flex-wrap
flex-flow
justify-content
align-items
具体各个属性值与作用参考
http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html