19
19
import java .io .IOException ;
20
20
import java .util .ArrayDeque ;
21
21
import java .util .Deque ;
22
+ import java .util .Iterator ;
22
23
import java .util .LinkedList ;
23
24
import java .util .List ;
24
25
import java .util .ListIterator ;
@@ -60,8 +61,12 @@ private static class Node {
60
61
// children listed in order by their utf8 label
61
62
private final LinkedList <Node > children ;
62
63
private Output output ;
63
- // Used during saving, -1 means the node has not been saved.
64
+
65
+ // Vars used during saving:
66
+
67
+ // -1 means the node has not been saved.
64
68
private long fp = -1 ;
69
+ private Iterator <Node > childrenIterator ;
65
70
66
71
Node (int label , Output output , LinkedList <Node > children ) {
67
72
this .label = label ;
@@ -102,11 +107,16 @@ void absorb(TrieBuilder trieBuilder) {
102
107
if (status != Status .BUILDING || trieBuilder .status != Status .BUILDING ) {
103
108
throw new IllegalStateException ("tries should be unsaved" );
104
109
}
105
- absorb (this .root , trieBuilder .root );
110
+ // Use a simple stack to avoid recursion.
111
+ Deque <Runnable > stack = new ArrayDeque <>();
112
+ stack .add (() -> absorb (this .root , trieBuilder .root , stack ));
113
+ while (!stack .isEmpty ()) {
114
+ stack .pop ().run ();
115
+ }
106
116
trieBuilder .status = Status .DESTROYED ;
107
117
}
108
118
109
- private static void absorb (Node n , Node add ) {
119
+ private static void absorb (Node n , Node add , Deque < Runnable > stack ) {
110
120
assert n .label == add .label ;
111
121
if (add .output != null ) {
112
122
n .output = add .output ;
@@ -118,8 +128,7 @@ private static void absorb(Node n, Node add) {
118
128
while (iter .hasNext ()) {
119
129
Node nChild = iter .next ();
120
130
if (nChild .label == addChild .label ) {
121
- // NO COMMIT: avoid this recursive impl.
122
- absorb (nChild , addChild );
131
+ stack .push (() -> absorb (nChild , addChild , stack ));
123
132
continue outer ;
124
133
}
125
134
if (nChild .label > addChild .label ) {
@@ -204,16 +213,11 @@ void saveNodes(IndexOutput index) throws IOException {
204
213
continue ;
205
214
}
206
215
207
- Node unSaved = null ;
208
- // NO COMMIT: this makes it a O(n^2) operation, we should avoid it.
209
- for (Node child : node .children ) {
210
- if (child .fp == -1 ) {
211
- unSaved = child ;
212
- break ;
213
- }
216
+ if (node .childrenIterator == null ) {
217
+ node .childrenIterator = node .children .iterator ();
214
218
}
215
- if (unSaved != null ) {
216
- stack .push (unSaved );
219
+ if (node . childrenIterator . hasNext () ) {
220
+ stack .push (node . childrenIterator . next () );
217
221
continue ;
218
222
}
219
223
0 commit comments