All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fireflysource.common.collection.trie.TreeTrie Maven / Gradle / Ivy

There is a newer version: 5.0.2
Show newest version
package com.fireflysource.common.collection.trie;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.*;


/**
 * A Trie String lookup data structure using a tree
 * 

* This implementation is always case-insensitive and is optimal for a variable * number of fixed strings with few special characters. *

*

* This Trie is stored in a Tree and is unlimited in capacity *

*

*

* This Trie is not Threadsafe and contains no mutual exclusion or deliberate * memory barriers. It is intended for an ArrayTrie to be built by a single * thread and then used concurrently by multiple threads and not mutated during * that access. If concurrent mutations of the Trie is required external locks * need to be applied. *

* * @param the entry type */ public class TreeTrie extends AbstractTrie { private static final int[] LOOKUP = { // 0 1 2 3 4 5 6 7 8 9 A B C D E F /*0*/-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*1*/-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*2*/31, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26, -1, 27, 30, -1, /*3*/-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 28, 29, -1, -1, -1, -1, /*4*/-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /*5*/15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /*6*/-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /*7*/15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, }; private static final int INDEX = 32; private final TreeTrie[] nextIndex; private final List> nextOther = new ArrayList<>(); private final char ch; private String key; private V value; @SuppressWarnings("unchecked") public TreeTrie() { super(true); nextIndex = new TreeTrie[INDEX]; ch = 0; } @SuppressWarnings("unchecked") private TreeTrie(char c) { super(true); nextIndex = new TreeTrie[INDEX]; this.ch = c; } private static void toString(Appendable out, TreeTrie t) { if (t != null) { if (t.value != null) { try { out.append(','); out.append(t.key); out.append('='); out.append(t.value.toString()); } catch (IOException e) { throw new RuntimeException(e); } } for (int i = 0; i < INDEX; i++) { if (t.nextIndex[i] != null) toString(out, t.nextIndex[i]); } for (int i = t.nextOther.size(); i-- > 0; ) toString(out, t.nextOther.get(i)); } } private static void keySet(Set set, TreeTrie t) { if (t != null) { if (t.key != null) set.add(t.key); for (int i = 0; i < INDEX; i++) { if (t.nextIndex[i] != null) keySet(set, t.nextIndex[i]); } for (int i = t.nextOther.size(); i-- > 0; ) keySet(set, t.nextOther.get(i)); } } @Override public void clear() { Arrays.fill(nextIndex, null); nextOther.clear(); key = null; value = null; } @Override public boolean put(String s, V v) { TreeTrie t = this; int limit = s.length(); for (int k = 0; k < limit; k++) { char c = s.charAt(k); int index = c >= 0 && c < 0x7f ? LOOKUP[c] : -1; if (index >= 0) { if (t.nextIndex[index] == null) t.nextIndex[index] = new TreeTrie(c); t = t.nextIndex[index]; } else { TreeTrie n = null; for (int i = t.nextOther.size(); i-- > 0; ) { n = t.nextOther.get(i); if (n.ch == c) break; n = null; } if (n == null) { n = new TreeTrie(c); t.nextOther.add(n); } t = n; } } t.key = v == null ? null : s; t.value = v; return true; } @Override public V get(String s, int offset, int len) { TreeTrie t = this; for (int i = 0; i < len; i++) { char c = s.charAt(offset + i); int index = c >= 0 && c < 0x7f ? LOOKUP[c] : -1; if (index >= 0) { if (t.nextIndex[index] == null) return null; t = t.nextIndex[index]; } else { TreeTrie n = null; for (int j = t.nextOther.size(); j-- > 0; ) { n = t.nextOther.get(j); if (n.ch == c) break; n = null; } if (n == null) return null; t = n; } } return t.value; } @Override public V get(ByteBuffer b, int offset, int len) { TreeTrie t = this; for (int i = 0; i < len; i++) { byte c = b.get(offset + i); int index = c >= 0 && c < 0x7f ? LOOKUP[c] : -1; if (index >= 0) { if (t.nextIndex[index] == null) return null; t = t.nextIndex[index]; } else { TreeTrie n = null; for (int j = t.nextOther.size(); j-- > 0; ) { n = t.nextOther.get(j); if (n.ch == c) break; n = null; } if (n == null) return null; t = n; } } return t.value; } @Override public V getBest(byte[] b, int offset, int len) { TreeTrie t = this; for (int i = 0; i < len; i++) { byte c = b[offset + i]; int index = c >= 0 && c < 0x7f ? LOOKUP[c] : -1; if (index >= 0) { if (t.nextIndex[index] == null) break; t = t.nextIndex[index]; } else { TreeTrie n = null; for (int j = t.nextOther.size(); j-- > 0; ) { n = t.nextOther.get(j); if (n.ch == c) break; n = null; } if (n == null) break; t = n; } // Is the next Trie is a match if (t.key != null) { // Recurse so we can remember this possibility V best = t.getBest(b, offset + i + 1, len - i - 1); if (best != null) return best; break; } } return t.value; } @Override public V getBest(String s, int offset, int len) { TreeTrie t = this; for (int i = 0; i < len; i++) { byte c = (byte) (0xff & s.charAt(offset + i)); int index = c >= 0 && c < 0x7f ? LOOKUP[c] : -1; if (index >= 0) { if (t.nextIndex[index] == null) break; t = t.nextIndex[index]; } else { TreeTrie n = null; for (int j = t.nextOther.size(); j-- > 0; ) { n = t.nextOther.get(j); if (n.ch == c) break; n = null; } if (n == null) break; t = n; } // Is the next Trie is a match if (t.key != null) { // Recurse so we can remember this possibility V best = t.getBest(s, offset + i + 1, len - i - 1); if (best != null) return best; break; } } return t.value; } @Override public V getBest(ByteBuffer b, int offset, int len) { if (b.hasArray()) return getBest(b.array(), b.arrayOffset() + b.position() + offset, len); return getBestByteBuffer(b, offset, len); } private V getBestByteBuffer(ByteBuffer b, int offset, int len) { TreeTrie t = this; int pos = b.position() + offset; for (int i = 0; i < len; i++) { byte c = b.get(pos++); int index = c >= 0 && c < 0x7f ? LOOKUP[c] : -1; if (index >= 0) { if (t.nextIndex[index] == null) break; t = t.nextIndex[index]; } else { TreeTrie n = null; for (int j = t.nextOther.size(); j-- > 0; ) { n = t.nextOther.get(j); if (n.ch == c) break; n = null; } if (n == null) break; t = n; } // Is the next Trie is a match if (t.key != null) { // Recurse so we can remember this possibility V best = t.getBest(b, offset + i + 1, len - i - 1); if (best != null) return best; break; } } return t.value; } @Override public String toString() { StringBuilder buf = new StringBuilder(); toString(buf, this); if (buf.length() == 0) return "{}"; buf.setCharAt(0, '{'); buf.append('}'); return buf.toString(); } @Override public Set keySet() { Set keys = new HashSet<>(); keySet(keys, this); return keys; } @Override public boolean isFull() { return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy