Skip to content

Commit e6aa1cb

Browse files
ingvarcNeilFraser
authored andcommitted
[Java] replaces synchronized Stack with Deque and refactors some other methods (google#18)
1 parent f7ec085 commit e6aa1cb

File tree

3 files changed

+43
-60
lines changed

3 files changed

+43
-60
lines changed

java/src/name/fraser/neil/plaintext/diff_match_patch.java

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,7 @@
2121
import java.io.UnsupportedEncodingException;
2222
import java.net.URLEncoder;
2323
import java.net.URLDecoder;
24-
import java.util.ArrayList;
25-
import java.util.Arrays;
26-
import java.util.HashMap;
27-
import java.util.LinkedList;
28-
import java.util.List;
29-
import java.util.ListIterator;
30-
import java.util.Map;
31-
import java.util.Stack;
24+
import java.util.*;
3225
import java.util.regex.Matcher;
3326
import java.util.regex.Pattern;
3427

@@ -763,8 +756,8 @@ public void diff_cleanupSemantic(LinkedList<Diff> diffs) {
763756
return;
764757
}
765758
boolean changes = false;
766-
Stack<Diff> equalities = new Stack<Diff>(); // Stack of qualities.
767-
String lastequality = null; // Always equal to equalities.lastElement().text
759+
Deque<Diff> equalities = new ArrayDeque<Diff>(); // Double-ended queue of qualities.
760+
String lastEquality = null; // Always equal to equalities.peek().text
768761
ListIterator<Diff> pointer = diffs.listIterator();
769762
// Number of characters that changed prior to the equality.
770763
int length_insertions1 = 0;
@@ -781,7 +774,7 @@ public void diff_cleanupSemantic(LinkedList<Diff> diffs) {
781774
length_deletions1 = length_deletions2;
782775
length_insertions2 = 0;
783776
length_deletions2 = 0;
784-
lastequality = thisDiff.text;
777+
lastEquality = thisDiff.text;
785778
} else {
786779
// An insertion or deletion.
787780
if (thisDiff.operation == Operation.INSERT) {
@@ -791,35 +784,35 @@ public void diff_cleanupSemantic(LinkedList<Diff> diffs) {
791784
}
792785
// Eliminate an equality that is smaller or equal to the edits on both
793786
// sides of it.
794-
if (lastequality != null && (lastequality.length()
787+
if (lastEquality != null && (lastEquality.length()
795788
<= Math.max(length_insertions1, length_deletions1))
796-
&& (lastequality.length()
789+
&& (lastEquality.length()
797790
<= Math.max(length_insertions2, length_deletions2))) {
798-
//System.out.println("Splitting: '" + lastequality + "'");
791+
//System.out.println("Splitting: '" + lastEquality + "'");
799792
// Walk back to offending equality.
800-
while (thisDiff != equalities.lastElement()) {
793+
while (thisDiff != equalities.peek()) {
801794
thisDiff = pointer.previous();
802795
}
803796
pointer.next();
804797

805798
// Replace equality with a delete.
806-
pointer.set(new Diff(Operation.DELETE, lastequality));
799+
pointer.set(new Diff(Operation.DELETE, lastEquality));
807800
// Insert a corresponding an insert.
808-
pointer.add(new Diff(Operation.INSERT, lastequality));
801+
pointer.add(new Diff(Operation.INSERT, lastEquality));
809802

810803
equalities.pop(); // Throw away the equality we just deleted.
811-
if (!equalities.empty()) {
804+
if (!equalities.isEmpty()) {
812805
// Throw away the previous equality (it needs to be reevaluated).
813806
equalities.pop();
814807
}
815-
if (equalities.empty()) {
808+
if (equalities.isEmpty()) {
816809
// There are no previous equalities, walk back to the start.
817810
while (pointer.hasPrevious()) {
818811
pointer.previous();
819812
}
820813
} else {
821814
// There is a safe equality we can fall back to.
822-
thisDiff = equalities.lastElement();
815+
thisDiff = equalities.peek();
823816
while (thisDiff != pointer.previous()) {
824817
// Intentionally empty loop.
825818
}
@@ -829,7 +822,7 @@ public void diff_cleanupSemantic(LinkedList<Diff> diffs) {
829822
length_insertions2 = 0;
830823
length_deletions1 = 0;
831824
length_deletions2 = 0;
832-
lastequality = null;
825+
lastEquality = null;
833826
changes = true;
834827
}
835828
}
@@ -1052,8 +1045,8 @@ public void diff_cleanupEfficiency(LinkedList<Diff> diffs) {
10521045
return;
10531046
}
10541047
boolean changes = false;
1055-
Stack<Diff> equalities = new Stack<Diff>(); // Stack of equalities.
1056-
String lastequality = null; // Always equal to equalities.lastElement().text
1048+
Deque<Diff> equalities = new ArrayDeque<Diff>(); // Double-ended queue of equalities.
1049+
String lastEquality = null; // Always equal to equalities.peek().text
10571050
ListIterator<Diff> pointer = diffs.listIterator();
10581051
// Is there an insertion operation before the last equality.
10591052
boolean pre_ins = false;
@@ -1064,7 +1057,7 @@ public void diff_cleanupEfficiency(LinkedList<Diff> diffs) {
10641057
// Is there a deletion operation after the last equality.
10651058
boolean post_del = false;
10661059
Diff thisDiff = pointer.next();
1067-
Diff safeDiff = thisDiff; // The last Diff that is known to be unsplitable.
1060+
Diff safeDiff = thisDiff; // The last Diff that is known to be unsplittable.
10681061
while (thisDiff != null) {
10691062
if (thisDiff.operation == Operation.EQUAL) {
10701063
// Equality found.
@@ -1073,11 +1066,11 @@ public void diff_cleanupEfficiency(LinkedList<Diff> diffs) {
10731066
equalities.push(thisDiff);
10741067
pre_ins = post_ins;
10751068
pre_del = post_del;
1076-
lastequality = thisDiff.text;
1069+
lastEquality = thisDiff.text;
10771070
} else {
10781071
// Not a candidate, and can never become one.
10791072
equalities.clear();
1080-
lastequality = null;
1073+
lastEquality = null;
10811074
safeDiff = thisDiff;
10821075
}
10831076
post_ins = post_del = false;
@@ -1096,42 +1089,42 @@ public void diff_cleanupEfficiency(LinkedList<Diff> diffs) {
10961089
* <ins>A</del>X<ins>C</ins><del>D</del>
10971090
* <ins>A</ins><del>B</del>X<del>C</del>
10981091
*/
1099-
if (lastequality != null
1092+
if (lastEquality != null
11001093
&& ((pre_ins && pre_del && post_ins && post_del)
1101-
|| ((lastequality.length() < Diff_EditCost / 2)
1094+
|| ((lastEquality.length() < Diff_EditCost / 2)
11021095
&& ((pre_ins ? 1 : 0) + (pre_del ? 1 : 0)
11031096
+ (post_ins ? 1 : 0) + (post_del ? 1 : 0)) == 3))) {
1104-
//System.out.println("Splitting: '" + lastequality + "'");
1097+
//System.out.println("Splitting: '" + lastEquality + "'");
11051098
// Walk back to offending equality.
1106-
while (thisDiff != equalities.lastElement()) {
1099+
while (thisDiff != equalities.peek()) {
11071100
thisDiff = pointer.previous();
11081101
}
11091102
pointer.next();
11101103

11111104
// Replace equality with a delete.
1112-
pointer.set(new Diff(Operation.DELETE, lastequality));
1105+
pointer.set(new Diff(Operation.DELETE, lastEquality));
11131106
// Insert a corresponding an insert.
1114-
pointer.add(thisDiff = new Diff(Operation.INSERT, lastequality));
1107+
pointer.add(thisDiff = new Diff(Operation.INSERT, lastEquality));
11151108

11161109
equalities.pop(); // Throw away the equality we just deleted.
1117-
lastequality = null;
1110+
lastEquality = null;
11181111
if (pre_ins && pre_del) {
11191112
// No changes made which could affect previous entry, keep going.
11201113
post_ins = post_del = true;
11211114
equalities.clear();
11221115
safeDiff = thisDiff;
11231116
} else {
1124-
if (!equalities.empty()) {
1117+
if (!equalities.isEmpty()) {
11251118
// Throw away the previous equality (it needs to be reevaluated).
11261119
equalities.pop();
11271120
}
1128-
if (equalities.empty()) {
1121+
if (equalities.isEmpty()) {
11291122
// There are no previous questionable equalities,
11301123
// walk back to the last known safe diff.
11311124
thisDiff = safeDiff;
11321125
} else {
11331126
// There is an equality we can fall back to.
1134-
thisDiff = equalities.lastElement();
1127+
thisDiff = equalities.peek();
11351128
}
11361129
while (thisDiff != pointer.previous()) {
11371130
// Intentionally empty loop.
@@ -1868,7 +1861,7 @@ public LinkedList<Patch> patch_make(String text1, LinkedList<Diff> diffs) {
18681861
patch.length2 += aDiff.text.length();
18691862
}
18701863

1871-
if (aDiff.text.length() >= 2 * Patch_Margin) {
1864+
if (aDiff.text.length() >= 2 * Patch_Margin && !patch.diffs.isEmpty()) {
18721865
// Time for a new patch.
18731866
if (!patch.diffs.isEmpty()) {
18741867
patch_addContext(patch, prepatch_text);

java/tests/name/fraser/neil/plaintext/Speedtest.java

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@
1313

1414
package name.fraser.neil.plaintext;
1515

16-
import name.fraser.neil.plaintext.diff_match_patch;
17-
1816
import java.io.BufferedReader;
1917
import java.io.FileReader;
2018
import java.io.IOException;
2119

2220
public class Speedtest {
2321

24-
public static void main(String args[]) {
22+
public static void main(String args[]) throws IOException {
2523
String text1 = readFile("tests/name/fraser/neil/plaintext/Speedtest1.txt");
2624
String text2 = readFile("tests/name/fraser/neil/plaintext/Speedtest2.txt");
2725

@@ -30,32 +28,28 @@ public static void main(String args[]) {
3028

3129
// Execute one reverse diff as a warmup.
3230
dmp.diff_main(text2, text1, false);
33-
System.gc();
3431

35-
long start_time = System.currentTimeMillis();
32+
long start_time = System.nanoTime();
3633
dmp.diff_main(text1, text2, false);
37-
long end_time = System.currentTimeMillis();
38-
System.out.printf("Elapsed time: %f\n", ((end_time - start_time) / 1000.0));
34+
long end_time = System.nanoTime();
35+
System.out.printf("Elapsed time: %f\n", ((end_time - start_time) / 1000000000.0));
3936
}
4037

41-
private static String readFile(String filename) {
38+
private static String readFile(String filename) throws IOException {
4239
// Read a file from disk and return the text contents.
43-
StringBuffer strbuf = new StringBuffer();
40+
StringBuilder sb = new StringBuilder();
41+
FileReader input = new FileReader(filename);
42+
BufferedReader bufRead = new BufferedReader(input);
4443
try {
45-
FileReader input = new FileReader(filename);
46-
BufferedReader bufRead = new BufferedReader(input);
4744
String line = bufRead.readLine();
4845
while (line != null) {
49-
strbuf.append(line);
50-
strbuf.append('\n');
46+
sb.append(line).append('\n');
5147
line = bufRead.readLine();
5248
}
53-
49+
} finally {
5450
bufRead.close();
55-
56-
} catch (IOException e) {
57-
e.printStackTrace();
51+
input.close();
5852
}
59-
return strbuf.toString();
53+
return sb.toString();
6054
}
6155
}

java/tests/name/fraser/neil/plaintext/diff_match_patch_test.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -944,11 +944,7 @@ private static String[] diff_rebuildtexts(LinkedList<Diff> diffs) {
944944

945945
// Private function for quickly building lists of diffs.
946946
private static LinkedList<Diff> diffList(Diff... diffs) {
947-
LinkedList<Diff> myDiffList = new LinkedList<Diff>();
948-
for (Diff myDiff : diffs) {
949-
myDiffList.add(myDiff);
950-
}
951-
return myDiffList;
947+
return new LinkedList<Diff>(Arrays.asList(diffs));
952948
}
953949

954950
public static void main(String args[]) {

0 commit comments

Comments
 (0)