iOS 哈希碰撞
一、問題背景
最近遇到一個(gè)生產(chǎn)問題,hash碰撞引發(fā)的頁面卡死。原始需求是想把一個(gè)數(shù)組隨機(jī)打散,開發(fā)同學(xué)手抄了百度的一篇文章文章連接 。
-(NSMutableArray*)getRandomArrFrome:(NSArray*)arr
{
NSMutableArray *newArr = [NSMutableArray new];
while (newArr.count != arr.count) {
//生成隨機(jī)數(shù)
int x =arc4random() % arr.count;
id obj = arr[x];
if (![newArr containsObject:obj]) {
[newArr addObject:obj];
}
}
return newArr;
}
這是網(wǎng)摘的代碼片段,本身沒什么大的問題,containsObject方法的時(shí)候需要重寫- (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
二、問題產(chǎn)生
當(dāng)時(shí)開發(fā)的同學(xué)思路是這樣,起一個(gè)while,從原始數(shù)組里隨機(jī)選擇一個(gè)數(shù)據(jù)塞到目標(biāo)數(shù)組中,N個(gè)循環(huán)之后判斷原始數(shù)組和目標(biāo)數(shù)組個(gè)數(shù)相等,就認(rèn)為打散任務(wù)完成。而判斷相等的條件是model中的name屬性做hash運(yùn)算(至于為什么這么做已經(jīng)無從考證)。
上午的生成問題排查的結(jié)果就是發(fā)現(xiàn)兩個(gè)字符串hash過后的結(jié)果一致@"200179032648"和@"200179026087",導(dǎo)致while死循環(huán)。
三、問題解決
換一種思路來實(shí)現(xiàn)亂序,在此就不贅述,直接貼代碼
- (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;
}