I have an approach that seems to work, though I feel like I must be misusing something to achieve it.
I am implementing a keyword matching algorithm to a Java 8 IntStream. The goal is to walk over a stream of char values (created by calling .chars() on an input string called sentence). If a keyword matches, it is returned with its replacement value, otherwise the original characters are returned unmodified.
The code I have written so far looks like this: the Replacer is implemented as a Consumer<Character> with some stateful properties:
class Replacer implements Consumer<Character> {
StringBuffer out;
StringBuffer buffer;
KeywordTrieNode current_keyword_trie_node;
KeywordTrieNode keyword_trie_root;
public Replacer(KeywordTrieNode keyword_trie_root) {
this.keyword_trie_root = keyword_trie_root;
this.current_keyword_trie_node = keyword_trie_root;
this.out = new StringBuffer();
this.buffer = new StringBuffer();
}
@Override
public void accept(Character c) {
KeywordTrieNode node = current_keyword_trie_node.get(c);
if (node != null) {
buffer.append(c);
current_keyword_trie_node = node;
} else {
String keyword = current_keyword_trie_node.get();
if (keyword != null) {
out.append(keyword);
} else {
out.append(buffer);
}
out.append(c);
buffer = new StringBuffer();
current_keyword_trie_node = this.keyword_trie_root;
}
}
@Override
public String toString() {
// Flush the buffer
String keyword = current_keyword_trie_node.get();
if (keyword == null) {
out.append(buffer);
} else {
out.append(keyword);
}
return out.toString();
}
}
Then to use this I have this function:
public String replace(String sentance) {
return replace(sentance.chars());
}
public String replace(IntStream stream) {
Replacer replacer = new Replacer(this.keyword_trie_root);
stream.mapToObj(c -> (char) c).forEachOrdered(replacer);
return replacer.toString();
}
Here the String is converted into a IntStream, the stream is then mapped into a stream of char values (which are autoboxed into Character which is needed for the underlying Map inside the keyword_trie_root).
Then the replacer is passed to forEachOrdered allowing it to see each character and build a bigger and bigger StringBuffer until it's toString() is invoked (performing one final buffer flush).
This doesn't feel like the correct use of Java streams but I'm hitting a bit of a wall when trying to reimagine this as a Combiner which I think is the correct way to solve this problem. Any ideas?
KeywordTrieNodeimplementation. \$\endgroup\$