说起 KO,你以为是这样的吗?
![cc87ee00bc38e75a4f99b61a7f202e45.png](https://i-blog.csdnimg.cn/blog_migrate/b17a1df7ae3402dc09cb739c2d677bcf.jpeg)
K.O.
背景
Java 的世界里有很多的 XO 了,什么 VO,BO,DTO,DAO 不一而足,让人看了就头疼,还有必要搞出一个 KO 来吗?
实际上是很有必要的,我们来考察一个场景
从数据库查询出如下数据
![68a3d9ad44177e00f7c46c4d52aac433.png](https://i-blog.csdnimg.cn/blog_migrate/e53e9f13aa5043e8ec2d66c512371f30.jpeg)
底价设置
我们将该数据缓存到 Map,减少数据库访问,缓存的 key 先放一边,value 就是上图中的底价
现在是 3 个参数才能确定 key,分别是 资源包id,竞价类型,优化类型,怎么构造这个 key 呢?
- 方案一: 使用分隔符将 3 个参数连接成一个字符串,即 String key = {资源包id}-{竞价类型}-{优化类型}
- 方案二: 三个参数都是 10 以内的数字,我们可以考虑用位运算生成一个对应的整数,即 int key = {资源包id}<<4 | {竞价类型} <<2 | {优化类型},这个方案并非通用方案,使用场景比较有限
- 方案三: 聚合 3 个整数的 KO
什么是 KO
所谓 KO 是专用于组合 key 的对象,含义为 key object;一个标准的 KO 应该满足如下条件
- 继承自 Object,且为 final 类
- 必须提供带参数的构造方法,且该方法为唯一的构造方法
- 建议使用静态工厂方法来创建实例,此时构造方法应为私有的
- 在构造方法里计算出 hashcode
- 类属性是 final 的
- 必须重写 hashCode(), equals()
- 建议重写 toString()
示例:一个组合 imei(整数),sn(字符串)的 KO
import java.util.Objects;public final class ImeiSnKo { private final Long imei; private final String sn; private final int hashCode; public static final ImeiSnKo create(Long imei, String sn) { return new ImeiSnKo(imei, sn); } private ImeiSnKo(Long imei, String sn) { this.imei = imei; this.sn = sn; this.hashCode = 31 * Objects.hashCode(imei) + Objects.hashCode(sn); } @Override public int hashCode() { return hashCode; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj instanceof ImeiSnKo) { ImeiSnKo ko = (ImeiSnKo) obj; return Objects.equals(imei, ko.imei) && Objects.equals(sn, ko.sn); } return false; }}
KO 的优势
和拼接字符串构造 key 来对比
- 含义明确,提升代码可读性
- 性能优势:无需进行字符串拼接操作
- 内存占用优势:没有产生新的字符串对象