Comparator排序需严格返回负数/0/正数;字符串不可用减法;降序应交换参数而非乘-1;多字段排序需嵌套判断并防空指针;中文模糊搜索应预存拼音、清理全角空格;TreeSet中修改排序字段须删除重加;分页必须先过滤再排序。

Comparator 排序时 compareTo 返回值写错导致顺序颠倒
Java 里 Comparator 的 compareTo 方法必须严格返回负数、0、正数,不能只用 return a - b 这种写法对 int 成立,但对 String 或自定义字段(比如姓名拼音首字母)直接减会出错——String 没有重载减法,编译不过;更常见的是误写成 return name1.compareTo(name2) * -1,结果翻转逻辑没生效,因为 compareTo 本身已含符号。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 按姓名升序:直接
return contact1.getName().compareTo(contact2.getName()) - 想降序?别乘 -1,改用
return contact2.getName().compareTo(contact1.getName()) - 多字段排序(先按部门,再按姓名):用
Integer.compare()或嵌套判断,避免空指针,例如:if (!Objects.equals(c1.getDept(), c2.getDept())) return c1.getDept().compareTo(c2.getDept()); else return c1.getName().compareTo(c2.getName()); - 用
Comparator.nullsFirst()包一层,防止getName()返回null报NullPointerException
模糊搜索匹配不到中文名,正则 or indexOf 都失效
用户输“张”,想匹配“张三”“李张伟”“小张”,但用 name.contains(input) 拿不到“李张伟”——因为 contains 是子串匹配,而“张”在“李张伟”中间,其实能匹配;真正卡住的是输入带空格、全角字符、或大小写混用,比如搜“zhang”却要匹配“张三”(拼音)。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 纯中文子串搜索:直接用
name.indexOf(input) >= 0或name.contains(input),比正则快且安全 - 支持拼音模糊(如输“zhang”匹配“张三”):引入
pinyin4j库,预存每个联系人的拼音字符串(如"zhangsan"),搜索时统一转小写再indexOf - 去掉输入两端空格和全角空格:
input = input.trim().replaceAll(" ", "")(注意全角空格是U+3000) - 不建议用
Pattern.compile(".*" + input + ".*"),容易被特殊字符(如.、*)破坏,必须先Pattern.quote(input)
用 TreeSet 管理联系人,新增后排序不更新
TreeSet 初始化时传了 Comparator,但后续调用 add() 新增对象后,发现集合没按预期重排——不是排序失效,而是 TreeSet 依赖插入时的比较结果建红黑树,它不会在插入后重新扫描全部元素。问题往往出在:联系人对象字段被修改了,但 TreeSet 不知道,导致内部结构错乱,甚至 contains() 返回 false。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 联系人对象的所有参与排序的字段(如
name、phone)必须设为final,或至少不在加入TreeSet后修改 - 真要改名?删掉再加回:
contacts.remove(oldContact); oldContact.setName(newName); contacts.add(oldContact); - 更稳妥的做法:不用
TreeSet自动维护顺序,改用ArrayList+ 每次搜索前调用Collections.sort(list, comparator),虽然多一次排序开销,但语义清晰、无隐式陷阱 - 如果数据量大(>1000 条),排序成本明显,就用
ArrayList存储,搜索时只对结果filter,排序留到展示层(比如 JavaFX 的SortedList)
搜索结果分页时 Comparator 和模糊条件组合出错
用户输入“王”,选按电话号码排序,结果第 1 页显示“王五 138…”,第 2 页突然冒出“张三 139…”——这是因为先分页再排序,还是先排序再分页?模糊搜索是过滤动作,必须在排序前完成,否则分页切片会漏掉本该排前面的匹配项。
实操建议:
立即学习“Java免费学习笔记(深入)”;
- 严格顺序:先
stream().filter(...)模糊匹配 → 再.sorted(comparator)→ 最后.skip((page-1)*size).limit(size) - 别在数据库层做模糊搜索再丢给 Java 排序,MySQL 的
LIKE '%xxx%'无法走索引,大数据量下慢;Java 内存中过滤适合几百条以内的通讯录 - 如果联系人超 5000 条,考虑用
Lucene建轻量索引,但要注意中文分词器配置(如SmartChineseAnalyzer对人名切分不准,换成IKAnalyzer更稳)
排序和搜索看似独立,但一旦涉及对象字段变更、中文处理、分页边界,三者就会互相咬死——最常被忽略的是:修改对象后没重建集合,或者把模糊逻辑塞进了 Comparator 里试图“边排边搜”。










