ConcurrentSuffixTree implements SuffixTree<O>, PrettyPrintable, Serializable { @Override public O putIfAbsent(CharSequence key, O value) { radixTree.acquireWriteLock(); try { String keyString = CharSequences.toString(key); final O existingValue = valueMap.putIfAbsent(keyString, value); if (existingValue == null) { addSuffixesToRadixTree(keyString); } return existingValue; } finally { radixTree.releaseWriteLock(); } } ConcurrentSuffixTree(NodeFactory nodeFactory); @Override O put(CharSequence key, O value); @Override O putIfAbsent(CharSequence key, O value); @Override boolean remove(CharSequence key); @Override O getValueForExactKey(CharSequence key); @Override Iterable<CharSequence> getKeysEndingWith(CharSequence suffix); @Override Iterable<O> getValuesForKeysEndingWith(final CharSequence suffix); @Override Iterable<KeyValuePair<O>> getKeyValuePairsForKeysEndingWith(final CharSequence suffix); @Override Iterable<CharSequence> getKeysContaining(final CharSequence fragment); @Override Iterable<O> getValuesForKeysContaining(final CharSequence fragment); @Override Iterable<KeyValuePair<O>> getKeyValuePairsForKeysContaining(final CharSequence fragment); @Override int size(); @Override Node getNode();  }
@Test public void testPutIfAbsent() throws Exception { ConcurrentSuffixTree<Integer> tree = newConcurrentSuffixTreeForUnitTests(); tree.putIfAbsent("BANANA", 1); tree.putIfAbsent("BANANA", 2); String expected = "○\n" + "├── ○ A ([BANANA])\n" + "│ └── ○ NA ([BANANA])\n" + "│ └── ○ NA ([BANANA])\n" + "├── ○ BANANA ([BANANA])\n" + "└── ○ NA ([BANANA])\n" + " └── ○ NA ([BANANA])\n"; String actual = PrettyPrinter.prettyPrint(tree); assertEquals(expected, actual); assertEquals(Integer.valueOf(1), tree.getValueForExactKey("BANANA")); }