iOS 哈希碰撞
一、问题背景
最近遇到一个生产问题,hash碰撞引发的页面卡死。原始需求是想把一个数组随机打散,开发同学手抄了百度的一篇文章文章连接 。
-(NSMutableArray*)getRandomArrFrome:(NSArray*)arr
{
NSMutableArray *newArr = [NSMutableArray new];
while (newArr.count != arr.count) {
//生成随机数
int x =arc4random() % arr.count;
id obj = arr[x];
if (![newArr containsObject:obj]) {
[newArr addObject:obj];
}
}
return newArr;
}
这是网摘的代码片段,本身没什么大的问题,containsObject方法的时候需要重写- (BOOL)isEqual:(id)object方法。于是就有了以下的改造
@implementation TestModel
- (BOOL)isEqual:(TestModel *)object {
BOOL same = self.hash == object.hash;
if (same) {
NSLog(@"%@:%lu=================%@:%lu",self.name,(unsigned long)self.hash,object.name,(unsigned long)object.hash);
}
return same;
}
- (NSUInteger)hash {
return self.name.hash;
}
@end
二、问题产生
当时开发的同学思路是这样,起一个while,从原始数组里随机选择一个数据塞到目标数组中,N个循环之后判断原始数组和目标数组个数相等,就认为打散任务完成。而判断相等的条件是model中的name属性做hash运算(至于为什么这么做已经无从考证)。
上午的生成问题排查的结果就是发现两个字符串hash过后的结果一致@"200179032648"和@"200179026087",导致while死循环。
三、问题解决
换一种思路来实现乱序,在此就不赘述,直接贴代码
- (NSArray *)getRandomArrayFrom:(NSArray *)arr
{
NSMutableArray *resultArray = [NSMutableArray arrayWithArray:arr];
for (int i = 0; i <arr.count; i++) {
int index = arc4random() % arr.count;
[resultArray exchangeObjectAtIndex:i withObjectAtIndex:index];
}
return resultArray;
}
网友评论