❝沉淀、分享、成长,让自己和他人都能有所收获!? ❞
图 15-1 写好代码的核心
为什么你的代码一坨坨?其实来自你有那么多为什么你要这样写代码!
「最终」,所有的这些不合理交织在一起,就是你能看到的一坨坨的代码!「所以」,要想把代码写好、写美,写到自己愿意反复欣赏,那么基本需要你有一定的:基础能力(数据结构、算法逻辑、设计模式)、应用能力(系统架构、开发经验)、拓展能力(产品思维),这三方面综合起来才能更好的开发程序。
但可能杠精会喊,我就写个CRUD要什么逻辑、什么数据结构,还算法?
但写CRUD并不一定业务需求是CRUD,只是你的知识面和技术深度只能把它设计成CRUD,用ifelse和for循环在一个类里反复粘贴复制罢了。
可能同样的需求交给别人手里,就会想的更多搭建的更加完善。就像:树上10只鸟开一枪还剩下几只,你会想到什么?比如:
所以,你还相信写程序只是简简单单的搞CRUD吗?接下来小傅哥再带着你搞几个例子看一看!
数据结构:数组、链表、红黑树 算法逻辑:哈希、扰动函数、负载因子、拉链寻址、
其实我们所开发的业务程序,哪怕是CRUD也都是对数学逻辑的具体实现过程。只不过简单的业务有简单的数学逻辑、复杂的业务有复杂的数学逻辑。数学逻辑是对数据结构的使用,(例如:把大象装进冰箱分几步
)合理的数据的结构有利于数据逻辑的实现和复杂程度。
在我们常用的API中,HashMap 就是一个非常好的例子,既有非常好的数据结构的使用,也有强大的数学逻辑的实现。为此也让 HashMap 成为开发过程中非常常用的API,当然也成为面试过程中最常问的技术点。
图 15-2 HashMap中的数据结构和数学逻辑
「重点」,HashMap 中涉及的知识点非常多,包括数据结构的使用、数组、链表、红黑树,也包括算法逻辑的实现:哈希、扰动函数、负载因子、拉链寻址等等。而这些知识如果可以深入的搞清楚,是完全不需要死记硬背的,也不需要为了面试造火箭。就像如下问题:
「看到了吗?」 HashMap完全就是对数据结构的综合使用,以及对数学逻辑的完美结合,才让我们有了非常好用的HashMap。这些知识的学习就可以技术迁移到我们自己业务开发中,把有些业务开发优化到非常不错的性能体现上。同时你的代码也值得加薪!
「哈希下标」
图 15-2 中涉及到的下标位置存放的数据,不是胡乱写的。是按照 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万单词的字典表。关于HashMap的内容小傅哥已经整理到面经手册中,链接:面经手册 • 拿大厂Offer
图 15-3 模仿得物(毒) APP抽奖码需求
图 15-3 是我们模拟得物APP中关于抽奖码需求的样式图,核心技术点包括:
在你没有看实现方案前,你可以先考虑下这样的唯一的随机码该怎样去生成。
int codeId = RedisUtil.incr("codeUUID");
String UUID = String.format("%08d", codeId);
System.out.println(UUID);
// 测试结果
00000001
00000002
00000003
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());
// 测试结果
qvY0Fqrk
8uyehK3H
U7z2v4qK
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)));
}
// 测试结果
uxdDQOG001
uxd8Uoj001
uxdERuG000
「实现方案」,终究不会一次就完美,还需要不断的优化完善。除此之外也会有很多其他的思路,例如电商生成订单号的方案也可以考虑设计,另外你以为这就完事了?当你已经工作多年,那么你每一天其实都在解决技术问题也是数学问题,产品的需求也更像是数学作业!加油数学老师!