ConcurrentTree extends ConcurrentTreeNode<K, V> { public List<V> getMatches(final K[] path) { final List<V> values = new LinkedList<V>(); ConcurrentTreeNode<K, V> node = this; for (final K part : path) { if (node.getValue() != null) { values.add(node.getValue()); } node = node.getChild(part); if (node == null) { break; } } if ((node != null) && (node.getValue() != null)) { values.add(node.getValue()); } Collections.reverse(values); return values; }  synchronized void add(final K[] path, final V value); synchronized V remove(final K[] path); V get(final K[] path); List<V> getMatches(final K[] path); @Override String toString();  }
@Test public void testGetMatches() { ConcurrentTree<String, String> tree = setupTree(); List<String> matches = tree.getMatches(delimiter.split("b/a/c/d/e/f/g")); assertNotNull(matches); assertEquals(matches.size(), 3); assertEquals(matches.get(0), "b/a/c/d/e/f"); assertEquals(matches.get(1), "b/a/c/d"); assertEquals(matches.get(2), "b/a"); matches = tree.getMatches(delimiter.split("b/a/c/c/e/f/g")); assertEquals(matches.size(), 1); assertEquals(matches.get(0), "b/a"); matches = tree.getMatches(delimiter.split("/b/a/c/d/e/f/g")); assertNotNull(matches); assertTrue(matches.isEmpty()); matches = tree.getMatches(delimiter.split("b assertTrue(matches.isEmpty()); matches = tree.getMatches(delimiter.split("b/ /a/c/d/e/f/g")); assertTrue(matches.isEmpty()); matches = tree.getMatches(delimiter.split("b/a assertFalse(matches.isEmpty()); }