一个含了不同维度的字符串在逻辑上如何定义相等的抽象设计

背景

这个标题确实有点儿不知所措,我实在不知道该如何定义下面我将要分析的场景,但我认为这种隐含的思想还是重要的。大概的场景是这样的,在设计上我们对设备的货舱型号进行了一定编码,比如:G1_G2G2_G1,F6_G1等等,但是在统计时,需求期望的是将G1_G2G2_G1看做是一个

如何设计G1_G2G2_G1相等

暴力法

if ("G2_G1".equals(key)) {
    key = "G1_G2";
} else if ("F6_G1".equals(key)) {
    key = "G1_F6";
} else if ("F6_G2".equals(key)) {
    key = "G2_F6";
}

在最开始我写下了此般丑陋的代码。代码丑陋点儿问题也不大,关键是想到以后可能会有G11_G2这样的情况我还是不能忍的。尽管这种对货舱型号编码的设计方式本身就有点儿,无法理解?

我开始思考这样的需求,本质是,我们重新定义了“相等”,G1_G2G2_G1两者从字符串自身的相等逻辑来讲是不会相等的,但迫于需求的我们需要重新对等号定义一下,我们该思考,它的本质是什么

可以很容易的发现,这样的字符串有一个明显的性质,就是交换顺序了,那么我们能不能将这个相等定义为满足交换律?就比如f(a,b)=f(b,a),我试图想象着有没有什么数学公式满足交换律,这样f我就可以很容易的出来了。但是结果并非如此,假如我们找到了一个数学公式,eg.f(a,b)=a+b,我们知道加法是满足交换律的,但是f(a,b)最终的值将会变得不那么可逆了,这获取将会为我们计算代码中的key产生障碍,因此我们在使用数学公式,不仅仅需要考虑交换性,还需要考虑唯一性可逆性,好的,我承认如果这样研究下去我们将会考虑的越来越复杂,但这不正是乐趣吗?但是迫于时间,带着大道至简的信仰,我不得不重新分析一下G1_G2G2_G1的性质是什么

幸运的是,我想到了它还有一个蕴涵比较深的性质无序性,这里的无序性是我们在应用层面重新定义了相等而来的,为什么无序?因为我们期望的是{G1,G2}与{G2,G1}是相等的,但在字符串中,它本身是有序的,所以我们期望的是无序,那么我们在思考一下,如何判断无序是否相等呢?我们已经将G1_G2G2_G1转换成了{G1,G2}{G2,G1}集合本身是无序的,因此这两个集合相等的,但是作为程序我们应该如何判断相等?我的答案是排序,让无序的数据重新排序,我们便可以简洁的判断出它们的相等。但我们需要注意的是,相等的本质是无序,排序是判断相等的一种手段,基于此我们可以幸运的处理推广如:G1_G2_G3这样的数据,并且介于此关于上一板块中提到的可逆性也是满足的。

上述长篇大论的分析了我的思维过程,是陶醉的

以重排序定义相等

key = reordering(key);
//...
public String reordering(String key) {
   String[] keySplit = key.split("_");
   Arrays.sort(keySplit);
   return String.join("_", keySplit);
}

reordering是我们重新定义的相等,在传入G1_G2G2_G1,key都将变成G1_G2

这样代码是不是简洁且灵活了很多。任何事物都是有规律可循的,不管是什么,肯定有一定的规则在衍生、进化、毁灭,尽管我们看起来是杂乱的、随机的

你可能感兴趣的:(代码细节之道,java,算法)