shz.core.st.triest.ConcurrentLTrieST Maven / Gradle / Ivy
package shz.core.st.triest;
import shz.core.queue.a.LArrayQueue;
import shz.core.stack.l.LLinkedStack;
import java.util.function.Function;
import java.util.function.Predicate;
/**
* 值为E类型的基于单词查找树的符号表
*
* 8+24+2*r(r为chars数组长度)=chars
* 8+[49+E(类型字节)+8*r+对齐填充]*n(n为元素个数)+8*r*n*w(w为键的平均长度)
*
* B=48*(n+1)+[E+对齐填充]*n+8*r*n*(w+1)+8+(2*r+n+对齐填充)
*/
public class ConcurrentLTrieST extends ConcurrentTrieST> {
private static final long serialVersionUID = 6841739733748860787L;
/**
* 8+E(类型字节)+25+8*r(r为数组长度)+对齐填充
*
* B=49+E(类型字节)+8*r+对齐填充
*
* 若E为String,r=4(例如基因序列A,T,C,G),则B=49+64+2*n(n为字符串长度)+8*4=113+2*n+32=145+2*n+对齐填充
*/
protected static final class Node extends ConcurrentTrieST.Node> {
private static final long serialVersionUID = -2975632615923083889L;
public E val;
@SuppressWarnings("unchecked")
public Node(int r) {
super(new Node[r]);
}
}
public ConcurrentLTrieST(char[] chars) {
super(chars);
root = new Node<>(chars.length);
}
public static ConcurrentLTrieST of(char[] chars) {
return new ConcurrentLTrieST<>(chars);
}
public final void put(char[] a, E val) {
if (val == null) throw new NullPointerException();
acceptWrite(() -> {
Node x = root;
for (char c : a) {
int i = charIndex.idx(c);
if (x.next[i] == null) x.next[i] = new Node<>(len);
x = x.next[i];
}
x.val = val;
x.leaf = true;
});
}
public final E get(char[] a, int d) {
return applyRead(() -> {
Node x = get(root, a, d);
return x == null || !x.leaf ? null : x.val;
});
}
public final E get(char[] a) {
return get(a, a.length);
}
public final LArrayQueue getAll() {
return applyRead(() -> get(root));
}
protected final LArrayQueue get(Node x) {
LArrayQueue queue = LArrayQueue.of();
if (x != null) {
LLinkedStack> stack = LLinkedStack.of();
push(stack, x);
while (!stack.isEmpty()) {
Node pop = stack.pop();
if (pop.leaf) queue.offer(pop.val);
push(stack, pop);
}
}
return queue;
}
private void push(LLinkedStack> stack, Node x) {
if (x.next == null) return;
for (int i = 0; i < len; ++i) if (x.next[i] != null) stack.push(x.next[i]);
}
public final LArrayQueue getByPrefix(char[] prefix) {
return applyRead(() -> get(get(root, prefix, prefix.length)));
}
public final LArrayQueue getChars(Predicate super E> predicate, int limit) {
return applyRead(() -> getChars0(x -> predicate == null || predicate.test(x.val), limit));
}
public final E computeIfAbsent(char[] a, Function func) {
E oldVal = get(a);
if (oldVal != null) return oldVal;
return applyWrite(() -> {
Node x = get(root, a, a.length);
if (x != null && x.leaf) return x.val;
E val = func.apply(a);
put(a, val);
return val;
});
}
}