title: Fast ordered list matching algorithm in Java
body: <p>I have a list of rules in the form</p>
  
  <p>L1 -> (A, B, C)</p>
  
  <p>L2 -> (D, E),</p>
  
  <p>L3 -> (F, G, A),</p>
  
  <p>L4 -> (C, A)</p>
  
  <p>.....</p>
  
  <p>This list contains ~30k such rules.</p>
  
  <p>I have an input in the form (X, Y, Z)</p>
  
  <p>This creates a method </p>
  
  <pre><code>List &lt;Rule&gt; matchRules(input)
  </code></pre>
  
  <p>Which belongs to a class RuleMatcher</p>
  
  <p>I started with a very simple clear naive solution, in order to get the framework down, get something working. </p>
  
  <pre><code>public RuleMatcher(Collection&lt;Rule&gt; rules) {
     this.rules = rules;
  }
  
  public Collection&lt;Rule&gt; matchRules(List&lt;Token&gt; input) {
     List&lt;Rule&gt; matchingRules = new ArrayList&lt;&gt;();
     for(Rule r: this.rules) {
          if(r.matches(input)) {
              matchingRules.add(r);
          }
     }
     return matchingRules; 
  }
  </code></pre>
  
  <p>Where <code>matches</code> is a very simple function that checks if the lengths are the same, and then checks each token as a for loop. </p>
  
  <p>This matchRules function is called in the magnitude of billions of times.</p>
  
  <hr>
  
  <p>Obviously this is a very poor implementation. According to my profiler at least half of the execution time is is spent in this matches function.</p>
  
  <p>I was thinking of two possible solutions:</p>
  
  <p>A. Some sort of Trie data structure holding the chains of rules which could be matched.</p>
  
  <p>B. some sort of hash function. Each symbol is given a unique identifier. Unfortunately, there are about 8 thousand unique symbols so this might be difficult.</p>
  
  <p>C. Make a hashmap conditioning on the size of the right hand side, the number of tokens in the rule. Unfortunately, the majority of the rules are about the same size, so this may not even be worthwhile. </p>
  
  <p>D. Some awesome solution one of you come up with. </p>
  
  <p>I hope somebody can shed some light on this problem.</p>
  
  <hr>
  
  <p>Edit: A token is just an object with a unique number. For example "NN" is a token. Each instance of "NN" is exactly the same.</p>
  
  <p>Matches code:</p>
  
  <pre><code>public boolean rhsMatches(List&lt;Token&gt; tokens) {
     if(tokens.size()!=rhsSize()) return false;
     for(int i = 0;i&lt;rhsSize();i++) {
        if(!rightSide.get(i).equals(tokens.get(i)) {
          return false;
        }
     }
     return true;
  }
  </code></pre>
  
  <p>Its not very pretty, but its simple. </p>