这里借用了commons-text包下的StringsComparator类来实现。首先引入依赖:
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.10.0</version>
</dependency>
接下来编写工具类:
package com.xxx;
import lombok.Data;
import org.apache.commons.text.diff.CommandVisitor;
import org.apache.commons.text.diff.EditScript;
import org.apache.commons.text.diff.StringsComparator;
import java.util.ArrayList;
import java.util.List;
/**
* @Author: zdf @Date: 2023/3/31 11:06:33 @Description:
*/
public class TextComparer {
public static List<Difference> compare(String source, String compareTo) {
StringsComparator comparator = new StringsComparator(source, compareTo);
EditScript<Character> script = comparator.getScript();
MyCommandsVisitor myCommandsVisitor = new MyCommandsVisitor();
script.visit(myCommandsVisitor);
myCommandsVisitor.finish();
List<Difference> differenceList = myCommandsVisitor.getDifferenceList();
return differenceList;
}
@Data
private static class MyCommandsVisitor implements CommandVisitor<Character> {
List<Difference> differenceList = new ArrayList<>();
int deleteIndex = 0;
int insertIndex = 0;
boolean lastIsDelete = false;
boolean lastIsInsert = false;
int continueDeleteLen = 0;
int continueInsertLen = 0;
@Override
public void visitDeleteCommand(Character character) {
lastIsInsert = false;
if (continueInsertLen > 0) {
differenceList.add(
new Difference(
Difference.INSERTED, insertIndex - continueInsertLen, continueInsertLen));
continueInsertLen = 0;
}
if (lastIsDelete) {
continueDeleteLen++;
} else {
continueDeleteLen = 1;
lastIsDelete = true;
}
deleteIndex++;
}
@Override
public void visitInsertCommand(Character character) {
lastIsDelete = false;
if (continueDeleteLen > 0) {
differenceList.add(
new Difference(Difference.DELETED, deleteIndex - continueDeleteLen, continueDeleteLen));
continueDeleteLen = 0;
}
if (lastIsInsert) {
continueInsertLen++;
} else {
continueInsertLen = 1;
lastIsInsert = true;
}
insertIndex++;
}
@Override
public void visitKeepCommand(Character character) {
lastIsInsert = false;
lastIsDelete = false;
if (continueInsertLen > 0) {
differenceList.add(
new Difference(
Difference.INSERTED, insertIndex - continueInsertLen, continueInsertLen));
continueInsertLen = 0;
}
if (continueDeleteLen > 0) {
differenceList.add(
new Difference(Difference.DELETED, deleteIndex - continueDeleteLen, continueDeleteLen));
continueDeleteLen = 0;
}
deleteIndex++;
insertIndex++;
}
public void finish() {
if (continueInsertLen > 0) {
differenceList.add(
new Difference(
Difference.INSERTED, insertIndex - continueInsertLen, continueInsertLen));
}
if (continueDeleteLen > 0) {
differenceList.add(
new Difference(Difference.DELETED, deleteIndex - continueDeleteLen, continueDeleteLen));
}
}
}
}
package com.xxx;
public class Difference {
public static final int DELETED = 0x102;
public static final int INSERTED = 0x103;
private int type;
private int index;
private int len;
public Difference() {
super();
}
public Difference(int type, int index, int len) {
super();
this.type = type;
this.index = index;
this.len = len;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
public int getLen() {
return len;
}
public void setLen(int len) {
this.len = len;
}
public String toString() {
return (type == DELETED ? "-" : "+") + "[" + index + ", " + (index + len) + "]";
}
}
对比效果展示:
其中展示效果可根据需求自定义