40亿个手机号码如何去重?

40亿个手机号码如何去重?

一、概述

常见的面试题:文件中有40亿个手机号码,请设计算法对手机号码去重,内存限制1G

二、 排序

最直接简单的方式是对所有的手机号码进行排序,重复的手机号码必然相邻,保留第一个,去掉后面重复的就行。

显然,排序的时间复杂度太高了

三、HashMap

既然直接排序的时间复杂度太高,那就用HashMap,具体思路是把手机号码记录到HashMap中,用HashMap的key唯一来去重。

实际要存40亿手机号码,1G的内存够分配这么多空间吗?显然不行

三、文件切割

显然,这是海量数据问题。工作中遇到过,很自然想到文件切割的方式(大文件拆成小文件),避免内存过大。拆分可以通过hashcode进行拆分,相同的手机号码会被拆分到同一个小文件中,之后在每个小文件去重。

这么多的文件操作,效率自然不高啊。

四、bitmap

可以对hashmap进行优化,采用bitmap这种数据结构,可以顺利地同时解决时间问题和空间问题。在很多实际项目中,bitmap经常用到。 一个unsigned int类型数据可以标识0~31这32个整数的存在与否。

/**
 * @author yangyc
 *     内存中装入头2位(手机号第一位始终为1,因此只需装入后面2位),需要99(2个9)个bit,
 *     99 bit = 99/8 byte =12.375 byte
 *     BitSet bitSet=new BitSet(99);
 *
 *   内存中装入手机号码后8位,需要99999999(8个9)个bit
 *   99999999 bit = (99999999/8) byte = (99999999 / (8 * 1024)) KB = (99999999 / 8 *1024*1024) M = 11.92M
 *       
 *   BitSet bitSet1= new BitSet(999999999);
 */

这样使用位图值为1时,就表明该数是存在的。而且通过bitmap记录,客观上就自动完成了排序功能。

五、总结

使用了 bitmap 之后,数字的排序功能、中位数、top-K问题等扩展问题都解决。一般海量的数据,而且有内存限制的问题都是通过 文件切割(大文件拆成小文件)或者bitmap位图 来解决

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以使用Java中的Stream API和Collectors工具类来根据某个字段对Map进行去重操作。下面是一个示例代码: ```java import java.util.*; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { List<Person> personList = new ArrayList<>(); personList.add(new Person("John", 25)); personList.add(new Person("Jane", 30)); personList.add(new Person("John", 35)); personList.add(new Person("Jane", 40)); Map<String, Person> uniqueMap = personList.stream() .collect(Collectors.toMap(Person::getName, p -> p, (p1, p2) -> p1)); System.out.println(uniqueMap); } } class Person { private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } ``` 在上面的示例中,我们有一个Person类,它有一个name字段和age字段。我们创建了一个包含了重复元素的personList列表。然后,我们使用Stream API的`toMap()`方法来将列表转换为Map,其中name字段作为键,Person对象作为值。在这个过程中,我们还传递了一个合并函数`(p1, p2) -> p1`,以确保当键冲突时只保留一个值。最后,我们打印出了去重后的Map。 输出结果为: ``` {Jane=Person{name='Jane', age=30}, John=Person{name='John', age=25}} ``` 这样,您就可以根据某个字段对Map进行去重了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值