目录
关于unity中判断GameObject是否为空使用obj==null性能消耗的问题
自己查阅资料整理的一些小的优化点,记录一下,有错误的地方有大佬发现也请指出,不甚感激。
c#中关于list<>的查找
仅查询是否包含此元素,Contains()效率最高,但只会返回bool值,使用哈希表或其他数据结构来进行快速查找,不会随着列表大小的增加而变慢,其时间复杂度通常为 O(1);
IndexOf()可以返回当前相同元素的index,会遍历整个列表来查找元素,重复元素时可能遍历多次,只返回首个相同元素index,匹配不到返回-1,会随着列表大小的增加而变慢,时间复杂度为 O(n);
FirstOrDefault()和IndexOf()类似,在查询时可以应对更复杂的比较情况,不会返回索引值,返回当前匹配到的元素,匹配不到返回0;
Find()和FirstOrDefault()使用类似,匹配不到返回空;
使用for循环虽然也是遍历,但是只遍历一次,也可以在匹配到相同元素后跳出,所以相对会节省一些性能;
关于快速比较两个list<Class>所包含相同元素
public class Class
{
public string name;
public int id;
//重写比较 //但是这里有装箱拆箱的操作
public override bool Equals(object obj)
{
if (obj == null || GetType() != obj.GetType())
return false;
TestClass other = (TestClass)obj;
return id == other.id && name == other.name;
}
public override int GetHashCode()
{
return HashCode.Combine(id, name);
}
}
//看实际使用决定用哪种方式重写
//实现 IEqualityComparer<Class> 接口并重写 Equals 和 GetHashCode 方法可避免装箱拆箱
class ClassEqualityComparer : IEqualityComparer<TestClass>
{
public bool Equals(TestClass x, TestClass y)
{
return x.id == y.id && x.name == y.name;
}
public int GetHashCode(TestClass obj)
{
return HashCode.Combine(obj.id, obj.name);
}
}
//使用示例
IEnumerable<Class> commonElements = list1.Intersect(list2);
//或者
IEnumerable<Class> commonElements = list1.Intersect(list2,new ClassEqualityComparer());
Intersect()相比嵌套for循环更简洁更高效
关于list<T>的排序
1.list<T>中的Sort(); // 默认按升序排序
2.LINQ中的OrderBy()
// 默认按升序排序 和OrderByDescending()
// 按降序排序
public class Class
{
public int id;
}
List<Class> list;//假如里面有数据
list.Sort((x, y) => x.id.CompareTo(y.id)); //Sort原地排序不会产生新的list更节省性能
List<Class> list_1 = list.OrderByDescending(x => x.id).ToList();//需要list接收,OrderBy用法一样
总结一下排序这里,Sort 在原有的list中排序,OrderBy会产生一个新list,不考虑使用场景只是排序,Sort会更高效。需要保留原有list就用OrderBy或OrderByDescending。
关于字符判断是否为空的比较
开发中经常遇到需要判断字符串是否为空的判断,经常出现的有几种方式:
//空字符串是指字符串长度为0 字符串为空代表的是字符串是null(有点绕。。。)
str == null;//判断字符串是否为null 字符串长度为0的时候"" 可以通过判断
str ==""; //判断字符串是否为空字符串,会临时创建一个空字符串,不建议使用
str.length==0; //根据字符串长度判断字符串是否为空字符串,最节省性能,只有一个整数比较
string.IsNullOrEmpty();//用于同时检查字符串是否为 null 或者为空字符串,相当于1,3结合比较
str.Equals(null) //不能这么用,始终都会返回false 而且如果字符串为空会抛异常
最常用的还是最后一种,这里只是解释一下这几种方式的区别 。(因为很久之前面试的时候遇到过这样的问题。)
关于unity中判断GameObject是否为空使用obj==null性能消耗的问题
先说我自己的结论,'=='运算有额外消耗,但是不大,而且'=='运算最为准确 ,可以使用.
经过种种查询得知,unity中重载了==运算符,来检测游戏对象obj是否为空,每次使用==unity不仅会检查内存地址,还会额外查询销毁状态,所以会多消耗一些性能,据说问题不大.
我查到有推荐使用ReferenceEquals(obj,null);节省性能,来判断obj是否为空的方式,
但我在实际测试的发现了一些问题:
图中代码只有obj1进行了拖拽赋值,其余都是空的,但是ReferenceEquals()却出现了问题,本来应该为空的obj2,obj4被判断为有值,只有私有的obj3得到了正确得判断.
这里就涉及到unity的特殊的处理了,public 会显示到面板上的游戏对象会被序列化,所以在私有的对象上面加上序列化就会造成一样的效果,unity给了他们一个不是空的空值...这个值unity自己是知道他是空的,所以通过unity重载的'=='运算符可以判断出正常的结果,ReferenceEquals()就不行了.
关于StringBuilder的使用
说到节省消耗StringBuilder总是少不了提到,但是这个什么用比较合适却一直没人说起,我们这里来简单的验证一下;
首先我们先了解一些StringBuilder()节省消耗的机制,它会在内部维护一个字符串数组,字符串频繁变更时相当于直接修改数组,普通'字符串'+'字符串'的操作会创建出新的对象,所以就会比较消耗性能.
但是这种字符串的+字符串的操作很快捷,简单易读,大家也很习惯了,所以我们就要实际的验证下,具体什么时候使用那种方式更合适.
这里我写了一个10000次for循环和很长的字符串,测试两种字符串拼接的时间,可以看出这种频繁的字符串操作StringBuilder()处理的时间可以说是遥遥领先;
这次循环100次,还缩短了字符串的长度,长度为10的字符串,时间差距就很小了 .
总结一下,处理很长,而且处理次数很多,而且频繁改动的数据(个人觉得最起码也要上百次的那种改动)就用StringBuilder();
不会频繁改动的,处理次数并不多的,直接+就好了.
整理补充中。。。