日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

一个手机号码剔重的问题

發(fā)布時(shí)間:2025/3/20 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 一个手机号码剔重的问题 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

問(wèn)題

QQ群上有人問(wèn)了這樣一個(gè)問(wèn)題, 現(xiàn)有2個(gè)待推廣手機(jī)號(hào)碼數(shù)據(jù)文件,A文件1000W行,B文件是100W,文件中每行記錄只有手機(jī)號(hào),號(hào)碼有重復(fù), 請(qǐng)?jiān)O(shè)計(jì)高效方案先對(duì)A、B數(shù)據(jù)文件分別進(jìn)行號(hào)碼剔重,再找出B文件中在A文件存在的號(hào)碼, 請(qǐng)寫(xiě)出核心設(shè)計(jì)思想,并編寫(xiě)代碼完整實(shí)現(xiàn)。(注:請(qǐng)用純c實(shí)現(xiàn),不許采用數(shù)據(jù)庫(kù)、Memcached等第三方中間件,號(hào)碼數(shù)據(jù)文件請(qǐng)自行模擬生成)? 答題要求:請(qǐng)同時(shí)提供Word設(shè)計(jì)文檔,和程序源代碼(如程序中使用了第三方Jar請(qǐng)注明,jar包請(qǐng)不要上傳),打包上傳。

思路及分析

我想了一下,看看《編程珠璣》,然后我決定用位圖(Bit Map)來(lái)解決這個(gè)問(wèn)題。? 有些朋友可能還不了解位圖(Bit Map),在這里我先用一個(gè)例子來(lái)說(shuō)明。 假設(shè)我有一個(gè)0到31的集合,集合里面的元素不重復(fù),比如這樣{0,3,1,5,2,19,7,8,31,21,10}。通過(guò)位圖,我可以將這樣的集合表示為11110001101000000001010000000001, 其中1表示該數(shù)值為下標(biāo)的數(shù)存在在集合中,比如第一個(gè)1表示0存在集合中,第二個(gè)1表示1存在集合中,等等。通過(guò)這樣做,我們起碼可以得到兩個(gè)好處 1) 節(jié)省空間--我們可以用二進(jìn)制一個(gè)位來(lái)存儲(chǔ)存儲(chǔ)兩個(gè)信息,一是存不存在,而是存在的數(shù)是多少(通過(guò)一個(gè)bit就可以得到這么多信息,真了不起)。 2) 排序--從左到右遍歷這個(gè)為圖,我們可以得到排序的集合,比如上例中,我們可以得到集合?{0,1,2,3,7,8,10,19,21,31} 如果將所有這電話號(hào)碼用位圖表示,那么需要9999999999個(gè)bit (10個(gè)9, 考慮到手機(jī)號(hào)碼的第一位都是1)。?9999999999 bit = (9999999999/8)?byte = (9999999999 / (8 * 1024)) KB = (9999999999 / 8 *1024*1024) M = 1192M 嗯....,1000萬(wàn)條手機(jī)號(hào)碼裝到內(nèi)存中只用114M左右的內(nèi)存空間,如果用位圖表示,看起來(lái)用的內(nèi)存更多。行不行啊.... 但是考慮到手機(jī)號(hào)碼的前3位都差不多,而且總數(shù)最多30個(gè),所有可能考慮把存放1000萬(wàn)條記錄的手機(jī)號(hào)碼的大文件拆分一下,這樣就位圖的位數(shù)就降2個(gè)數(shù)量級(jí)了。所以如果我們要在內(nèi)存中裝入手機(jī)號(hào)碼后8位,需要99999999(8個(gè)9)個(gè)bit,算一下 99999999 bit = (99999999/8)?byte = (99999999 / (8 * 1024)) KB = (99999999 / 8 *1024*1024) M = 11.92M 這樣好辦了,內(nèi)存夠用了。

號(hào)碼剔重步驟

根據(jù)以上的思路,第一步要大文件進(jìn)行拆分, 以下是Java代碼 package art.programming.algorithm;import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Writer; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set;import org.junit.Test;public class BigFileSpliter {private Map<String, Writer> fileWriterMap = new HashMap<String, Writer>();public void split(File file) throws IOException{ InputStream is; BufferedReader br; String line; is = new FileInputStream(file); br = new BufferedReader(new InputStreamReader(is));while((line = br.readLine()) != null){ //System.out.println(line); append(line.substring(0,3)+".txt", line); } closeAllWriters(); br.close(); is.close(); }public void append(String fileName, String appendStr) throws IOException{if (!fileWriterMap.containsKey(fileName)){ File file = new File(fileName); if(!file.exists()){ file.createNewFile(); } FileWriter fw = new FileWriter(file); fileWriterMap.put(fileName, fw); } fileWriterMap.get(fileName).write(appendStr); fileWriterMap.get(fileName).write('\n'); }public void closeAllWriters(){ for(Writer fw : fileWriterMap.values()){ try { fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally{ try { fw.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }public List<String> getAllFileNames(){ Set<String> keys = fileWriterMap.keySet(); List<String> klist = new ArrayList<String>(); for (String key : keys){ klist.add(key); }Collections.sort(klist); return klist; }@Test public void testSplit() throws IOException{ new BigFileSpliter().split(new File("cellphone.txt")); } }

第二步,將文件按照文件名排序,依次讀取文件中的電話號(hào)碼

第三步,將電話號(hào)碼放到位圖中,如果對(duì)應(yīng)的位是1,那么就不要放了(這樣就去重了) 第四步,遍歷位圖,位的值為1的輸出到文件中,如果算出的數(shù)不足8為10進(jìn)制的數(shù),前面補(bǔ)0, 比如838,前面補(bǔ)0,變成00000838 以下的Java程序是第二到第四步的實(shí)現(xiàn) package art.programming.algorithm;import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader;public class BigFileSort {private final static int RANGE = 32; private int[] bitMap;private File outputFile; private File inputFile; private int bitMapLen = (99999999/RANGE) + RANGE; FileWriter fw;public BigFileSort(String inputFileName, String outputFileName) throws IOException{ bitMap = new int[bitMapLen]; outputFile = new File(outputFileName); if (outputFile.exists()){ outputFile.delete(); } outputFile.createNewFile(); inputFile = new File(inputFileName); fw = new FileWriter(outputFile); }public void sortAndOutput() throws IOException{ BigFileSpliter bigFileSpliter = new BigFileSpliter(); bigFileSpliter.split(inputFile); for (String fileName : bigFileSpliter.getAllFileNames()){ readAndSetBitMap(fileName); output(fileName.substring(0, 3)); } //Clean up fw.close(); }private void readAndSetBitMap(String fileName) throws IOException{ InputStream is; BufferedReader br; String line; is = new FileInputStream(fileName); br = new BufferedReader(new InputStreamReader(is)); while((line = br.readLine()) != null){ long tmp = Long.parseLong(line.substring(3, 11)); int mod = (int) tmp / RANGE; int offset = (int) tmp % RANGE; int bit = bitMap[(int)mod]; if (getBit(bit, offset) != 1){ bit = setBit(bit, offset, 1); bitMap[(int)mod] = bit; }else{ System.out.println(fileName.subSequence(0, 3) + toStringRep(tmp) + " duplicates!"); } } br.close(); is.close(); }private void output(String prefix) throws IOException{for (int i=0; i< bitMapLen; i++){ for (int offset=0; offset<RANGE; offset++){ if (getBit(bitMap[i], offset) == 1){ long tmp = i * RANGE + offset; String cellphoneNum = toStringRep(tmp); fw.write(prefix+cellphoneNum); fw.write("\n"); } } }for (int i=0; i< bitMapLen; i++){ bitMap[i] = 0; } }private String toStringRep(long tmp){ String cellphoneNum = String.valueOf(tmp); if (cellphoneNum.length()<8){ StringBuilder sb = new StringBuilder(); for (int j=0; j< 8 - cellphoneNum.length(); j++){ sb.append('0'); } sb.append(cellphoneNum); cellphoneNum = sb.toString(); } return cellphoneNum; }private int getBit(int signinNum, int bitIndex) { if( (signinNum & ( 1 << bitIndex)) != 0){ return 1; } return 0; }private int setBit(int num, int bitIndex, int zeroOrOne){ if (zeroOrOne == 1){ num = num | (1 << bitIndex); }else{ num = num - (1 << bitIndex); } return num; }//整體測(cè)試以下 @Test public void testSort() throws IOException{ long begin = System.currentTimeMillis(); new BigFileSort("cellphone.txt", "sortedCellphone.txt").sortAndOutput(); System.out.println(System.currentTimeMillis() - begin); } }

整個(gè)過(guò)程,事件花費(fèi)大約60秒左右

手機(jī)號(hào)碼交集

將A、B文件分別剔重,可以得到電話號(hào)碼排好序的兩個(gè)文件。兩個(gè)文件順序?qū)Ρ染涂梢哉页鼋患恕?

轉(zhuǎn)載于:https://www.cnblogs.com/cando/p/3201351.html

總結(jié)

以上是生活随笔為你收集整理的一个手机号码剔重的问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。