关于大数据去重的两三事

P.S. 下文提到的数据基于iPhone 6S, iOS9.2(12C75)

OK, 转入正题,最近博主在公司里接到一个任务,需要在一个大约4万条数据的数据库中快速将数据Fetch出来,载入内存之中,然后根据这些数据的某一个字段进行快速排重检查,并把重复的对象进行分组显示。

接到这个任务,博主的第一反应就是把所有数据都取出来,然后把需要进行去重排序的那个值作为NSDictionary的Key,然后将那些对象组成一个Array,作为这个Key的Value,大致的代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
NSMutableArray *allData = [self allData];
for (Object *object in allData)
{
NSMutableArray *oneGroupObjects = result[object.someKey];
if (oneGroupObjects == nil)
{
oneGroupObjects = [[NSMutableArray alloc] init];
}
[oneGroupObjects addObject:object];

[result setObject:oneGroupObjects forKey:object.someKey];
}

OK, 搞定!

编译,安装,走你!

一看时间3s多一点点, 博主认为这个时间还算可以接受,毕竟在手机上,毕竟4万多条数据呢。

可是博主的Boss们可不这么认为,才4万多条数据,竟然就要话这么长时间!

没办法,改吧~

中间复杂的过程就不多赘述了,说说最后的结果吧。

首先,还是用CoreData把所有数据取出来,然后丢到一个容器里,丢容器里的原因一个是为了后续的遍历,另一个原因就是为了保证这些对象不会被ARC给自动释放了,为什么不能被释放?我们下面再说。
接着遍历这些取出来的数据,然后将数据组装到C语言的struct中,将这个这个对象的内存地址作为这个struct的ID。
然后将需要排序的值做一次快排,然后就能够根据顺序,将相同的组分出来了。
然后,就是将C的struct中的那个ID对象再转回CoreData对象,对!这就是为什么那些CoreData对象不能被自动释放的原因,这个内存地址是作为链接C语言算法和NSManagedObject对象的桥梁!
具体回转的代码如下:

1
2
void *p = (void *)( *oneResult);
NSManagedObject *obj = (__bridge NSManagedObject *)p;

OK,搞定!
再走你!0.4s,是不是非常炫!

总结:

Apple提供的各种容器提供了非常方便的各种方法,但是这些封装也是以性能损失为代价的,所以在处理非常大量的数据的时候还是应该对于特殊的情况,进行特殊处理。