跳槽到下家工资涨了8000,结果入职当天老板对他说:挖你的人把你夸得天花乱坠!你要好好干,不然对不起高工资
刚看到个贴子,说网友爆料:同事跳槽到新公司,工资一下涨了8000。结果入职第一天,老板当面说:挖你的人把你夸得天花乱坠,你可得好好干,不然对不起这钱。
我觉得这事吧,不用上纲上线。工资涨那么多,本来就意味着预期更高,你要先拿点真本事出来,让大家心里不犯嘀咕。怕的不是老板说这句话,怕的是自己心虚、只想高薪不想高配。
不过话说回来,老板也别老拿“对得起工资”压人,真想用好人才,就得用目标和结果说话,而不是天天念紧箍咒。
面试题:修复表中的名字
我跟你说个真事啊,昨天晚上十一点多,我在公司楼下拿奶茶,运营小姑娘冲过来一句: “东哥,你们这个报表是不是有 bug?用户名字咋有大写有小写,还有啥‘ zHaNg san ’这种妖魔鬼怪?”
我一看数据库,典型的“修复表中的名字”场景: 同一张表里,name 字段啥格式都有:全大写、全小写、大小写乱来、前后空格、多个空格,甚至还有空字符串。老板要的是:首字母大写、其他小写、单词之间一个空格,像人话一样。
虽然在线上一般用 SQL 一把梭,但很多时候你会把数据拉出来,用 Java 处理一遍再写回去,尤其是做批处理、数据清洗脚本的时候,所以就有了今天这个小算发…哦,算法。
先别急着看代码,先把问题捋清楚哈。一个名字我们大概要做几件事:
处理空值和全是空格的情况,不然一跑就 NullPointerException。去掉前后空格,中间如果有一堆空格要压成一个。 按“空格”把名字拆成一个个单词,比如 zhang san要拆成"zhang"、"san"。每个单词搞成:首字母大写,其余小写。 再用一个空格拼回去。
用人话说就是:先把名字“洗干净”,再“梳个头”,最后再“扎成一束”。
我先写了个最小单元的方法,只管修一个名字字符串,长这样:
publicclassNameFixer{
// 修复单个名字
publicstatic String fixName(String raw){
if (raw == null) {
returnnull; // 看需求,你也可以返回空字符串
}
// 1. 去掉前后空格
String trimmed = raw.trim();
if (trimmed.isEmpty()) {
return""; // 全是空格的,当成空名字
}
// 2. 把中间多个空格压成一个
// 正则里 \\s+ 表示一个或多个空白字符(空格、tab 等)
String normalizedSpace = trimmed.replaceAll("\\s+", " ");
// 3. 按空格拆成单词
String[] parts = normalizedSpace.split(" ");
StringBuilder sb = new StringBuilder();
for (int i = 0; i < parts.length; i++) {
String word = parts[i];
if (word.isEmpty()) {
continue;
}
// 4. 统一先转小写,再把首字母变成大写
String lower = word.toLowerCase();
char first = Character.toUpperCase(lower.charAt(0));
if (lower.length() == 1) {
sb.append(first);
} else {
sb.append(first).append(lower.substring(1));
}
if (i < parts.length - 1) {
sb.append(" ");
}
}
return sb.toString();
}
}
这个方法就解决了大部分脏数据,比如:
" zHaNg sAn "→"Zhang San"" li"→"Li""WANG"→"Wang"" "→""(空字符串)
逻辑其实挺顺的,对吧: 先 trim,再正则压空格,再 split,每个单词先 toLowerCase() 再 toUpperCase(first char)。
你可能会问,那放到“表”里咋搞,是不是得跟数据库打交道?我平时一般这么干:查出一批数据,用 Java 处理完再批量更新。随便写个伪代码给你感受下流程:
publicvoidfixUserNames(Connection conn)throws SQLException {
String selectSql = "SELECT id, name FROM user_table";
String updateSql = "UPDATE user_table SET name = ? WHERE id = ?";
try (PreparedStatement psSelect = conn.prepareStatement(selectSql);
PreparedStatement psUpdate = conn.prepareStatement(updateSql);
ResultSet rs = psSelect.executeQuery()) {
while (rs.next()) {
long id = rs.getLong("id");
String rawName = rs.getString("name");
String fixedName = NameFixer.fixName(rawName);
psUpdate.setString(1, fixedName);
psUpdate.setLong(2, id);
psUpdate.addBatch();
}
psUpdate.executeBatch();
}
}
这里有几个点随口唠一下:
一定用 PreparedStatement,别字符串拼 SQL,那玩意儿又丑又不安全。addBatch + executeBatch一起用,批量提交要比一条条executeUpdate快很多。真到生产,还得配合事务、分页(别一次把整表拉内存)、以及备份,毕竟这是“手术级”操作。
说回算法本身,复杂度也很直白: 假设总共有 N 个名字,每个名字平均长度 L,那整体就是 O(N * L),因为你对每个字符最多就扫几遍:trim/正则/遍历 都是线性的。 对这种文本清洗来说,这已经很友好了,更多瓶颈反而是 I/O(查表、回写)。清一下,不然过两天报表又得挨骂了。(顺手记一笔在这,算是自己的小技术笔记)
-END-
我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html