自己用的C#基础学习笔记(二)——C#面向对象(2)

第十一天

1.1 string stringbuffer stringbulider

1.三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String

2.String <StringBufferStringBuilder)的原因

String:字符串常量

StringBuffer:字符创变量

StringBuilder:字符创变量

  从上面的名字可以看到,String字符创常量,也就是不可改变的对象。对于这句话的理解你可能会产生这样一个疑问  ,比如这段代码:

1 String s = "abcd";
2 s = s+1;
3 System.out.print(s);// result : abcd1

  我们明明就是改变了String型的变量s的,为什么说是没有改变呢? 其实这是一种欺骗,JVM是这样解析这段代码的:首先创建对象s,赋予一个abcd,然后再创建一个新的对象s用来    

执行第二行代码,也就是说我们之前对象s并没有变化,所以我们说String类型是不可改变的对象了,由于这种机制,每当用String操作字符串时,实际上是在不断的创建新的对象,而原来的对象就会变为垃圾被GC回收掉,可想而知这样执行效率会有多底。

  而StringBufferStringBuilder就不一样了,他们是字符串变量,是可改变的对象,每当我们用它们对字符串做操作时,实际上是在一个对象上操作的,这样就不会像String一样创建一些而外的对象进行操作了,当然速度就快了。

3.一个特殊的例子:

1 String str = “This is only a” + “ simple” + “ test”;
3 StringBuffer builder = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);

 

  你会很惊讶的发现,生成str对象的速度简直太快了,而这个时候StringBuffer居然速度上根本一点都不占优势。其实这是JVM的一个把戏,实际上:

String str = “This is only a” + “ simple” + “test”;

  其实就是:

String str = “This is only a simple test”;

  所以不需要太多的时间了。但大家这里要注意的是,如果你的字符串是来自另外的String对象的话,速度就没那么快了,譬如:

String str2 = “This is only a”;

String str3 = “ simple”;

String str4 = “ test”;

String str1 = str2 +str3 + str4;

这时候JVM会规规矩矩的按照原来的方式去做。

4.StringBuilderStringBuffer

StringBuilder:线程非安全的

StringBuffer:线程安全的

当我们在字符串缓冲去被多个线程使用是,JVM不能保证StringBuilder的操作是安全的,虽然他的速度最快,但是可以保证StringBuffer是可以正确操作的。当然大多数情况下就是我们是在单线程下进行的操作,所以大多数情况下是建议用StringBuilder而不用StringBuffer的,就是速度的原因。

对于三者使用的总结:

1.如果要操作少量的数据用 = String

2.单线程操作字符串缓冲区 下操作大量数据 = StringBuilder

3.多线程操作字符串缓冲区 下操作大量数据 = StringBuffer

 

1.2 线程安全与不安全

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。 线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。

线程安全问题都是由全局变量静态变量引起的。

若每个线程中对全局变量、静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的;若有多个线程同时执行写操作,一般都需要考虑线程同步,否则的话就可能影响线程安全。

比如一个 ArrayList 类,在添加一个元素的时候,它可能会有两步来完成:1. Items[Size] 的位置存放此元素;2. 增大 Size 的值。

单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1

而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。

那好,我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是线程不安全了。

1.3 字符串操作函数

1.3.1 获取长度 字符串.Length

String s = “232”;s.Length;

1.3.2 大小写转换 str.ToUpper()大写  str.ToLoewr()小写

1.3.3 判断是否相等 str.Equals()

返回布尔值,括号加逗号可以看到重载。

第二个参数:StringComparison.OrdinalIgnoreCase是不区分大小写,默认不写区分。StringComparison是枚举类型。例如:str.Equals(“fsaff”, StringComparison.OrdinalIgnoreCase);

1.3.4 包含 str.Contains(“比较字符串”)

返回布尔值。

1.3.5 是否以某个字符串开始 str.StartsWith(“比较字符串”)

返回布尔值

1.3.6 是否以某个字符串结束 str.EndsWith(“比较字符串”)

返回布尔值

1.3.7 分割字符串 str.Split(char数组,StringSplitOptions.RemoveEmptyEntries);

第二个参数是处理空白字符(用于以空白字符串分割)。返回string类型的数组。

字符串会根据Char类型的数组中的字符来分割自己,且分割后的字符不包含char字符本身。

1.3.8 字符串与char数组转换

字符串本身是一个char类型的只读数组.并且使用str[n]的方式读取的数据类型是char,判断时需要用char类型来判断,否则会出错。

Char[] chs = str.ToCharArray();

Str = new string(chs);

1.3.9 字符串在某字符串中的开始位置和结束位置

Str.IndexOf(“比较字符串,开始数字,可以不写,默认从0开始找)

返回字符串所在索引数,没找到返回-1,索引从0开始

例如:str.IndexOf(“fsd”,6);从第六个开始找

Str.LastIndexOf(“比较字符串,开始数字,可以不写,默认从最后开始找)

倒着找,用法和上面一样

1.3.10 去掉空格

String str1 = Str.Trim();去掉前后空格,不能去中间的

String str1 =  Str.TrimEnd();去掉后面的空格

String str1 =  Str.TrimStart();去掉前面的空格

返回字符串,必须用字符串变量接收。

1.3.11 替换

Str.Replace(被替换字符串,替换成的内容);举例:

Str.Replace(“aa”,”bb”);

1.3.12 判断是否为空串或空字符串

空字符串虽然什么都没存,但是占用空间。Str=””;

空间null不占空间。Str=null; 可以用来释放空间

String.IsNullOrEmpty();

返回值为布尔值。

1.3.13 连接字符串 string.Join()

String s = stirng.Join(“|”,”dafsd”,”fdsfa”);

第一个是连接字符,后面是连接内容,后面可以用数组表示,int数组也可以

1.3.14 截取字符串

String ss = s.SubString(1);从第一字符开始截取到最后

String ss= s.SubString(1,3);从字符串的第一个位置开始截取,截取3个字符。

1.3.15 格式化字符串

String str = String.Format();按想要的格式输出。返回字符串

格式字符串形式内容:

1、 格式化货币(跟系统环境有关,中文人民币,英文美元)

String.Format(“{0:C}”,0.2)   结果¥0.20(英文系统$0.20

默认保留两位小数,可以指定:

String.Format(“{0:C1}”,0.2222)  结果¥0.2(自动四舍五入)

还可以一次性格式化多个:

String.Format(“市场价:{0:C},优惠价{1:C3}”,23.15,19.82);

2、 格式化十进制的数字(格式化成固定的位数,位数不能少于未格式化前,只支持整型)

String.Format(“{0:D3}”,23);  结果023

String.Format(“{0:D2}”,1232);  结果1232(2只能代表格式化的最小位数,不会自己取舍)

3、 用分号隔数字,并指定小数位数

String.Format(“{0:N}”,14200); 结果14,200.00(默认为两位小数)

String.Format(“{0:D3}”,14200.2345); 142.235(自动四舍五入)

4、格式化百分比

String.Format(“{0:P}”,0.24583); 24.58%默认两位小数

String.Format(“{0:P1}”,0.24583); 24.6%四舍五入

5、零占位符和数字占位符效果和第2条类似,但支持整数和小数

String.Format(“{0:0000.00}”,123456.344);123456.34

String.Format(“{0:0000.00}”,123.4455);0123.45

String.Format(“{0:####.##}”,123445.5645); 123445.56

String.Format(“{0:####.#}”,194.0394);194

空格占位符

String.Format(“{0,-50}”,”abcde”); //格式化成50个字符,原字符左对齐,不足则补充空格

String.Format(“{0,50}”,”abcde”); //格式化成50个字符,原字符右对齐,不足则补充空格

6、日期格式化

String.Format(“{0:d}”,System.DateTime.Now);2009-3-2

String.Format(“{0:D}”,System.DateTime.Now);2009320

String.Format(“{0:f}”,System.DateTime.Now);200932015:37

String.Format(“{0:F}”,System.DateTime.Now); 200932015:37:52

String.Format(“{0:g}”,System.DateTime.Now); 2009-3-2 15:37

String.Format(“{0:G}”,System.DateTime.Now); 2009-3-2 15:37:27

String.Format(“{0:m}”,System.DateTime.Now);320

String.Format(“{0:t}”,System.DateTime.Now);15:41

String.Format(“{0:T}”,System.DateTime.Now);15:41:50

1.4 数组类(数组操作函数)

属性

1

IsFixedSize
获取一个值,该值指示数组是否带有固定大小。

2

IsReadOnly
获取一个值,该值指示数组是否只读。

3

Length
获取一个 32 位整数,该值表示所有维度的数组中的元素总数。

4

LongLength
获取一个 64 位整数,该值表示所有维度的数组中的元素总数。

5

Rank
获取数组的秩(维度)。

下表列出了 Array 类中一些最常用的方法:

序号

方法 & 描述

1

Clear
根据元素的类型,设置数组中某个范围的元素为零、为 false 或者为 null

2

Copy(Array, Array, Int32)
从数组的第一个元素开始复制某个范围的元素到另一个数组的第一个元素位置。长度由一个 32 位整数指定。

3

CopyTo(Array, Int32)
从当前的一维数组中复制所有的元素到一个指定的一维数组的指定索引位置。索引由一个 32 位整数指定。

4

GetLength 
获取一个 32 位整数,该值表示指定维度的数组中的元素总数。

5

GetLongLength
获取一个 64 位整数,该值表示指定维度的数组中的元素总数。

6

GetLowerBound
获取数组中指定维度的下界。

7

GetType
获取当前实例的类型。从对象(Object)继承。

8

GetUpperBound
获取数组中指定维度的上界。

9

GetValue(Int32)
获取一维数组中指定位置的值。索引由一个 32 位整数指定。

10

IndexOf(Array, Object)
搜索指定的对象,返回整个一维数组中第一次出现的索引。

11

Reverse(Array)
逆转整个一维数组中元素的顺序。

12

SetValue(Object, Int32)
给一维数组中指定位置的元素设置值。索引由一个 32 位整数指定。

13

Sort(Array)
使用数组的每个元素的 IComparable 实现来排序整个一维数组中的元素。

14

ToString
返回一个表示当前对象的字符串。从对象(Object)继承。

 

1.5 ArrayList集合(动态数组) (不推荐用)

1.5.1 ArrayList集合

长度随便,类型随便,集合的元素都是object类型,任何元素添加到集合中后,都会被装箱成object类型

使用前,必须引用命名空间using System.Collections;

ArrayList list = new ArrayList();

List.Add(2);

List.Add(“sadfsda”);list.Add(对象);

Add();可以添加任意类型的变量值。

任何一个数据类型都可以使用is来判断,判断后都可以使用强制转换。例如,对象,数组,结构体等。

If(List[i] is int[]){

For(int j=0;j<((int[])list[i]).Length;i++){

Cw(((int[])list[i])[j]);

}

}

1.5.2 ArrayList方法(自己学习)

Add();添加元素

AddRange();可以将集合的元素直接添加的集合中,主要是集合和数组中的元素,用此函数会直接添加元素,不会出现输出只显示命名空间的情况

Remove(“元素值”);移除指定的元素。例如:list.Remove(3);移除值为3的元素

RemoveAt();移除下标的元素。例如:list.RemoveAt(0);移除第一个元素

List. RemoveRange();用于删除一批元素,通过指定开始的索引和删除的数量来删除List.Insert(位置,);插入一个元素,例如:list.Insert(3,”ddf”);第四个(下标为3的)就会变成ddf

List.InsertRange(位置,数组元素);插入一个集合

List.clear();移除集合中所有元素。

List.Reverse();反转

List.Sort ();升序排序

List.Contains();集合中是否包含某个元素,例如list.Contains(2);判断集合中是否包含2

TrimSize方法

这个方法用于将ArrayList固定到实际元素的大小,当动态数组元素确定不在添加的时候,可以调用这个方法来释放空余的内存。

ToArray方法

这个方法把ArrayList的元素Copy到一个新的数组中。Int32[] values = (Int32[])List.ToArray(typeof(Int32));

Int32[] values = new Int32[List.Count];

List.CopyTo(values);

 

 

1.6 键值对集合HashTable哈希表(类似PHP的字符串数组)

Hashtable中的元素存储在DictionaryEntry对象

命名空间和ArrayList一样,using Collections;

定义:Hashtable t = new Hashtable();

键是唯一的,通过键找值

添加:t.Add(“”,””);t.Add(true,false);t.Add(1.5f,”aa”);重复键使用add添加会报错。

或者 t[0] = 5;//添加一个键为0值为5的元素,t[“sdaf”] = “safs”;相同键会覆盖值

添加键值对没有顺序。

1.6.1 键值对的遍历

Foreach(var ii in t.Keys){

Console.WriteLine(“{0},值{1}”,ii,t[ii]);

}

Foreach(DictionaryEntry ii in t){

Console.WriteLine(“{0},值{1}”,ii.Key,ii.Value);

}

1.6.2 ArrayList长度

List.count 集合中实际存在的元素个数

List.Capacity 集合里最大的长度,即集合可以容纳多少个元素,根据实际的容纳量自动扩充的。永远比count大。

1.7 字典集合(键值对集合的一种)

Dictionary<键的类型,值的类型> 名称= new Dictionary<键的类型,值的类型>

例如:Dictionary<int,string> dis = new Dictionary<int,string>;

添加方式:

Dis.Add(1,”234234”);

Dis[4] = “dd”; 如果键已存在会覆盖,没有就会创建

字典长度:dis.Count

字典的遍历:

for循环不能遍历,哪怕字典键都是int也不能,因为可能存在空缺的键。

Foreach(KeyValuePair<int,string> item in dis){

Cw(“{0}{1}”,item.Key,item.Value);

}

Foreach(var fff in dis.Keys){

Cw(“{0}{1}”,fff,dis[fff]);

}

1.8 List泛型集合

List<T>   尖括号内T代表任意类型,是一个类型的占位符

例如:List<int> list = new List<int>();

list.Add(1); list.Add(2); list.Add(3);

list.AddRange(new int[]{5,6,7,8,9});

list.AddRange(list);

长度:list.Count

转成数组:ToArray();

Int[] aa= list.ToArray();

数组转集合:

List<int> ll = aa.ToList();

1.9 自定义的泛型类

Class 类名<T>  where  T:struct  

T是任意类型,where是类型限定(根据需要写,可以不写)struct是限定为值类型,class是限定引用类型。

IComparable是限定只能是本接口的子类。

T只是一个代表,使用什么字母都行,一般用T

Where T:Class,new();  限定为引用类型,并且使用了无参构造函数

举例:

Public class Person<T> where {

Private int _age;

Private T _a;

Public T A{}

Public void sayhello(){

}

}

调用:

Person<int> p = new Person<int>();

1.9.1 自定义泛型类的方法

Public void Change<T>(ref T a ,ref T b){就是在方法名后加上泛型符号

T temp = a;

A= b;

B = temp;

}

Int a =5;int b=8;

调用:p.Change<int>(ref a,ref b);

普通类中可以有泛型方法,泛型类中也可以有普通方法

1.10 重载运算符

自己去定义运算符的意义,只能在类中重载,也只能对重载所在类的对象起作用。

关键字:operator

1、 必须用public修饰

2、 必须是类的静态方法

3、 重载运算符==时,也必须重载!=运算符

4、 重载关系运算符>,>=时,也必须重载<,<=

5、 可以重载一元运算符:!++--,true,false

6、 可以重载的二元运算符:+-*/%&|^,<<,>>

7、 可以重载关系运算符:==,!=<,>,<=,>=

8、 一元运算符只能有一个参数,二元运算符有两个参数

9、 在某种情况下,参数的类型必须与声明的运算符的类或结构类型相同

举例:

public class Person{

public int num1{get;set;}

public int num2{get;set;}

//public static Person operator +(参数列表,该参数必须与类的结构或者运算符的结构相同){//重载加好运算符,

}

public static Person operator +(Person op1,Person op2){

  Person p = new Person();

p.num1=op1.num1+op2.num1+op1.num2+op2.num2;

p.num2=op1.num1+op2.num1;

renturn p;

}

}

调用:

Person p1= new person();

P1.num1 = 3;

P1.num2 = 5;

Person p2 = new person();

P2.num1 = 4;

P2.num2 = 8;

Person p = p1+p2;//此时加号就是重载过的双目运算符

Cw(“num1-{0},num2-{1}”,p.num1,p.num2);//p.num1=20;p.num2=7;

1.11 文件类File

处理小型文件的读取和写入,因为该类的方法会将文件整个内容都读取到内存中。该类属于静态类

使用需要导入system.IO类库

Flie.Create(路径及文件名,大小限制); 创建文件,返回值是fileStream

例如:File.Create(@“c:\cc\cc.txt”);

File.Delete(路径及文件名);删除文件,

建议删除创建之前先判断有没有,使用File.Exists();

File.Copy(复制的文件及路径,复制到的文件和路径名);粘贴文件

File.Copy(@“c:\cc\cc.txt”, @“c:\cc\bb.txt”);

剪切

File.Move(@“c:\cc\cc.txt”, @“c:\cc\bb.txt”);

上述方法的路径一定要存在,系统不会自动创建文件夹路径,并且,如果该文件已存在会直接报错

1.11.1 文件编码

存储文件:存储数据的一种表现形式。

乱码:存储文件和读取文件时编码方式不一样。

ASC码表 0-127  ASCII 0-255 GB2312  BIG5  Unicode(UTF-8, UTF-7)

一般使用UTF-8传输交互数据:3个字节表示一个汉字

1.11.2 文件类的操作

文件内容读取:

FileStream fs = File.Open(“路径文件名”,打开方式(FileMode.Open);

或者通过流的方式打开文件:FileStream fs = new FileStream(“路径Filemode.Append);

打开方式为FileMode.Open,后写入的内容会覆盖掉。Filemode.Append时不是覆盖,而是追加。

Fs.Read(字节数组,第几个开始,读几个);返回值是int,返回的内容是真是字节的长度,例如:Fs.Read(创建一个空字节数组,0buffer.length);

fs.Length字节流长度

str = File.ReadAllText(“路径”);返回字符串,读取所有文件内容为str

string[] strs = File.ReadAllLines(“路径”);返回字符串数组,每一行为数组的一个元素,读取文件内容的每一行为string数组

File.ReadAllBytes(路径及文件名);读取文件中所有行,然后关闭该文件,返回值byte[]字节数组

Encoding.编码格式.GetString(File.ReadAllBytes(路径及文件名));byte[]数组转化成字符串,返回值字符串。

Encoding system.Text类库的内容,需要先加载该命名空间

文件内容写入:

FileStrem Fs = Flie.Create(路径及文件名,大小限制);

Fs.Write(字节数,第几个开始写,写几个);使用该方法第一步应该讲对应字符串内容转化成字节数,但转换字节数,需要先获取编码。

Byte[] buffer = System.Text.Encoding.编码格式.GetBytes(str);f返回字节数组

写完后,必须将fs.Close();关闭文件流,负责会出现文件占用的问题。

此外还有File.WriteAllBytes方法

举例说明:string str = “dsfasdfafdsaf”;

Byte[] bb = Encoding.Default.GetBytes(str);//default是默认编码模式

File.WriteAllBytes(路径及名称,bb);该写入操作会直接将原文件内容覆盖掉。

1.11.3 FileInfo

FileInfo 是密封类:能继承别的类,别的类不能继承密封类,只能坐子类。

FileInfo是非静态类,用对象对文件进行操作。

例如: FileInfo s = new FileInfo(路径及文件名);

s.Create();

s.CopyTo();

s.MoveTo();

s.Delete();

1.11.4 对文件夹操作的静态类Directory

Directory是静态类

Directory.CreateDirectory(@“目录结构\文件夹名”);创建文件夹,已有不再创建

Bool exits = Directory.Exists(@“路径文件夹”);是否存在该文件夹

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值