掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
[[357374]]

目錄
一、前言
圖 15-1 寫好代碼的核心
「最終」,所有的這些不合理交織在一起,就是你能看到的一坨坨的代碼!「所以」,要想把代碼寫好、寫美,寫到自己愿意反復(fù)欣賞,那么基本需要你有一定的:基礎(chǔ)能力(數(shù)據(jù)結(jié)構(gòu)、算法邏輯、設(shè)計模式)、應(yīng)用能力(系統(tǒng)架構(gòu)、開發(fā)經(jīng)驗)、拓展能力(產(chǎn)品思維),這三方面綜合起來才能更好的開發(fā)程序。
但可能杠精會喊,我就寫個CRUD要什么邏輯、什么數(shù)據(jù)結(jié)構(gòu),還算法? 但寫CRUD并不一定業(yè)務(wù)需求是CRUD,只是你的知識面和技術(shù)深度只能把它設(shè)計成CRUD,用ifelse和for循環(huán)在一個類里反復(fù)粘貼復(fù)制罷了。
可能同樣的需求交給別人手里,就會想的更多搭建的更加完善。就像:樹上10只鳥開一槍還剩下幾只,你會想到什么?比如:
所以,你還相信寫程序只是簡簡單單的搞CRUD嗎?接下來小傅哥再帶著你搞幾個例子看一看!
二、代碼就是對數(shù)學(xué)邏輯的具體實現(xiàn)
數(shù)據(jù)結(jié)構(gòu):數(shù)組、鏈表、紅黑樹 算法邏輯:哈希、擾動函數(shù)、負(fù)載因子、拉鏈尋址、
其實我們所開發(fā)的業(yè)務(wù)程序,哪怕是CRUD也都是對數(shù)學(xué)邏輯的具體實現(xiàn)過程。只不過簡單的業(yè)務(wù)有簡單的數(shù)學(xué)邏輯、復(fù)雜的業(yè)務(wù)有復(fù)雜的數(shù)學(xué)邏輯。數(shù)學(xué)邏輯是對數(shù)據(jù)結(jié)構(gòu)的使用,(例如:把大象裝進(jìn)冰箱分幾步)合理的數(shù)據(jù)的結(jié)構(gòu)有利于數(shù)據(jù)邏輯的實現(xiàn)和復(fù)雜程度。
在我們常用的API中,HashMap 就是一個非常好的例子,既有非常好的數(shù)據(jù)結(jié)構(gòu)的使用,也有強(qiáng)大的數(shù)學(xué)邏輯的實現(xiàn)。為此也讓 HashMap 成為開發(fā)過程中非常常用的API,當(dāng)然也成為面試過程中最常問的技術(shù)點(diǎn)。
圖 15-2 HashMap中的數(shù)據(jù)結(jié)構(gòu)和數(shù)學(xué)邏輯
「重點(diǎn)」,HashMap 中涉及的知識點(diǎn)非常多,包括數(shù)據(jù)結(jié)構(gòu)的使用、數(shù)組、鏈表、紅黑樹,也包括算法邏輯的實現(xiàn):哈希、擾動函數(shù)、負(fù)載因子、拉鏈尋址等等。而這些知識如果可以深入的搞清楚,是完全不需要死記硬背的,也不需要為了面試造火箭。就像如下問題:
「哈希下標(biāo)」
圖 15-2 中涉及到的下標(biāo)位置存放的數(shù)據(jù),不是胡亂寫的。是按照 HashMap 中的計算邏輯找到的固定位置值。代碼如下:
- for (int i = 1; i < 1000; i++) {
- String key = String.valueOf(i);
- int hash = key.hashCode() ^ (key.hashCode() >>> 16);
- int idx = (64 - 1) & hash;
- if (idx == 2) {
- // System.out.println(i + " Idx:" + idx);
- }
- if (idx == 62) {
- System.out.println(i + " Idx:" + idx);
- }
- }
如果你需要英文的,那么可以跑10萬單詞的字典表。關(guān)于HashMap的內(nèi)容小傅哥已經(jīng)整理到面經(jīng)手冊中,鏈接:面經(jīng)手冊 ? 拿大廠Offer
三、得物(毒) 8位隨機(jī)抽獎碼設(shè)計
1. 需求描述
圖 15-3 模仿得物(毒) APP抽獎碼需求
圖 15-3 是我們模擬得物APP中關(guān)于抽獎碼需求的樣式圖,核心技術(shù)點(diǎn)包括:
在你沒有看實現(xiàn)方案前,你可以先考慮下這樣的唯一的隨機(jī)碼該怎樣去生成。
2. 實現(xiàn)方案
2.1 基于Redis生成
- int codeId = RedisUtil.incr("codeUUID");
- String UUID = String.format("%08d", codeId);
- System.out.println(UUID);
- // 測試結(jié)果
- 00000001
- 00000002
- 00000003
評分:?
方案:基于 Redis 的 incr 方法,全局自增從0開始,以上是偽代碼。
點(diǎn)評:以上方案不可用,除了并不一定能保證全局自增和可靠性外,有一個很大的問題是你的順序自增,把APP有多少人參加活動的數(shù)據(jù)暴露了。
2.2 隨機(jī)數(shù)生成
- Random random = new Random();
- StringBuffer code = new StringBuffer();
- for (int i = 0; i < 8; i++) {
- int number = random.nextInt(3);
- switch (number) {
- case 0:
- code.append((char) (random.nextInt(26) + 65)); // 65 ~ 90
- break;
- case 1:
- code.append((char) (random.nextInt(26) + 97)); // 97 ~ 122
- break;
- case 2:
- code.append((char) (random.nextInt(9) + 48)); // 48 ~ 97
- break;
- }
- }
- System.out.println(code.toString());
- // 測試結(jié)果
- qvY0Fqrk
- 8uyehK3H
- U7z2v4qK
評分:??
方案:基于隨機(jī)數(shù)生成8位隨機(jī)碼,相當(dāng)于62^8次冪,有將近百萬億的隨機(jī)數(shù)。
點(diǎn)評:此方案在很多業(yè)務(wù)場景中都有使用,但這里的實現(xiàn)還有一個問題,就是隨性后的不唯一性,雖然我們知道這么大體量很難出現(xiàn)兩個相同的。但如果隨著業(yè)務(wù)運(yùn)營日積月累的使用,終究會有兩個一樣的隨機(jī)數(shù),只要出現(xiàn)就會是客訴。所以還需要保證唯一性,可以在隨機(jī)數(shù)中加入年或者月的標(biāo)記,按照這個體量落庫用防重方式保證唯一。當(dāng)然你還可以有其他的方式來保證唯一
2.3 基于雪花算法
- final static char[] digits = { '0', '1', '3', '2', '4', '7', '6', '5', '8',
- 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
- '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
- 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y',
- 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
- 'Z', '0', '1', };
- public static void main(String[] args) {
- SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
- System.out.println(idWorker.nextId());
- long code = idWorker.nextId();
- char[] buf = new char[64];
- int charPos = 64;
- int radix = 1 << 6;
- long mask = radix - 1;
- do {
- buf[--charPos] = digits[(int) (code & mask)];
- code >>>= 6;
- } while (code != 0);
- System.out.println(new String(buf, charPos, (64 - charPos)));
- }
- // 測試結(jié)果
- uxdDQOG001
- uxd8Uoj001
- uxdERuG000
評分:???
方案:基于雪花算法的核心目的是,生成隨機(jī)串的本身就是唯一值,那么就不需要考慮重復(fù)性。只需要將唯一值轉(zhuǎn)換為對應(yīng)64進(jìn)制的字符串組合就可以了。
點(diǎn)評:這里的思路很好,但有幾個問題需要解決。首先是雪花算法的長度是18位,在轉(zhuǎn)換為64位時會會有10位長的隨機(jī)字符串組合,不滿足要求。另外大寫字母、小寫字母和數(shù)字組合是62個,還缺少2個不滿足64個,所以需要后面補(bǔ)充兩位,但這兩位生成的組合數(shù)需要廢棄?!改敲础梗绻凑者@個生成隨機(jī)串且保證唯一的思路,就需要完善雪花算法,降低位數(shù),在滿足業(yè)務(wù)自身的情況下,控制生成長度。
「實現(xiàn)方案」,終究不會一次就完美,還需要不斷的優(yōu)化完善。除此之外也會有很多其他的思路,例如電商生成訂單號的方案也可以考慮設(shè)計,另外你以為這就完事了?當(dāng)你已經(jīng)工作多年,那么你每一天其實都在解決技術(shù)問題也是數(shù)學(xué)問題,產(chǎn)品的需求也更像是數(shù)學(xué)作業(yè)!加油數(shù)學(xué)老師!
四、總結(jié)
好的程序?qū)崿F(xiàn)離不開數(shù)據(jù)結(jié)構(gòu)的設(shè)計、邏輯算法的完善、設(shè)計模式的考量,再配合符合業(yè)務(wù)發(fā)展和程序設(shè)計的架構(gòu)才能搭建出更加合理的程序。
在學(xué)習(xí)的過程中不要刻意去背答案、背套路,那不是理科內(nèi)容的學(xué)習(xí)方式。只有你更多的去實踐、去驗證,讓懂了就是真的懂,才更加舒心!
本篇又扯到了這,想問一句你是害怕35歲,還是害怕自己能力不及年齡增長?想學(xué)就把知識學(xué)透,你騙不了面試官,只能騙自己!

我們在微信上24小時期待你的聲音
解答本文疑問/技術(shù)咨詢/運(yùn)營咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流