工具类源码
使用
LCSDiff lcsDiff = new LCSDiff(str1, str2, new EnglishWordMetadataPicker()); // 元数据的定义:一个英文单词视为一个不可分割单元(元数据),英文字母外的其余字符,单个字符视为一个不可分割单元(元数据)
// LCSDiff lcsDiff = new LCSDiff(str1, str2); // 使用默认元数据采拣器的版本:单个char视为一个不可分割单元(元数据)
CommonInfo diff = lcsDiff.seekCommon();
CommonInfo:用于存储公共文本在两个字符串(str1和str2)中的位置
MetadataPicker:用于将字符串str1
、str2
处理为两组元数据组成的数组
元数据:表示在diff的过程中作为一个整体进行匹配的字符串,示例如下:
两个字符串str1和str2如下(为了方便演示,例子中选取的两个字符串都没有空格)
str1: 1+2=3one+two=three
str2: 11+2=13eleven+two=thirteen
定义他们由以下元数据组成(元数据间用空格分隔)
str1: 1 + 2 = 3 one + two = three
str2: 1 1 + 2 = 1 3 eleven + two = thirteen
那么匹配到的共同字符串将会是如下3个字符串:
1+2= 3 +two=
由于str1中的one和str2中的eleven都是元数据,所以one中的e字符和elevent中的e字符不能产生匹配
同理,由于str2中的数字13是由两个元数据1和3组成,所以13中的3能够与str1中等号后面的3产生匹配
元数据采拣器的选取非常重要,会影响diff效果的好坏,元数据采拣器的好坏以业务需求作为评定准则。此外,处理后元数据数组的长度将影响diff算法计算时占用的内存大小。
例如:
对代码进行diff这个业务逻辑,可以考虑用代码中的特殊符号如{
、}
、;
、空白字符
、换行符
等代码语句分割符来生成元数据,进行第一次diff。然后再用更细粒度的元数据采拣器,对初次匹配中不一致的行内容再进行一次diff。类似于Idea中的文件比较功能的效果,使用换行符进行第一次匹配,完整行不匹配的,会用一个较浅的颜色标记该行存在差异,再在行内部使用细粒度的差分再次匹配,然后用较深的颜色标记高亮显示出行内部细节上存在差异的点,这样在降低内存占用率的同时,又能让文件的差异一目了然。