|
@@ -1,327 +0,0 @@
|
|
|
-/*
|
|
|
|
|
- * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
|
|
- * @copyright Ranides Atterwim
|
|
|
|
|
- * @license WTFPL
|
|
|
|
|
- * @url http://ranides.net/projects/assira.drafts
|
|
|
|
|
- */
|
|
|
|
|
-package net.ranides.assira.collections.map.impl;
|
|
|
|
|
-
|
|
|
|
|
-import java.util.ArrayList;
|
|
|
|
|
-import java.util.Collection;
|
|
|
|
|
-import java.util.Collections;
|
|
|
|
|
-import java.util.Comparator;
|
|
|
|
|
-import java.util.HashMap;
|
|
|
|
|
-import java.util.Iterator;
|
|
|
|
|
-import java.util.List;
|
|
|
|
|
-import java.util.Map;
|
|
|
|
|
-import java.util.Map.Entry;
|
|
|
|
|
-import java.util.SortedMap;
|
|
|
|
|
-import java.util.SortedSet;
|
|
|
|
|
-import java.util.function.Function;
|
|
|
|
|
-import java.util.function.Supplier;
|
|
|
|
|
-import java.util.stream.Stream;
|
|
|
|
|
-import net.ranides.assira.collection.maps.ASortedMap;
|
|
|
|
|
-import net.ranides.assira.collection.maps.RBTreeMultiMap;
|
|
|
|
|
-import net.ranides.assira.collection.sets.ASortedSet;
|
|
|
|
|
-import net.ranides.assira.collection.sets.RBTreeMultiSet;
|
|
|
|
|
-
|
|
|
|
|
-import net.ranides.assira.collections.map.IndexMap;
|
|
|
|
|
-import net.ranides.assira.collections.map.IndexQuery;
|
|
|
|
|
-import net.ranides.assira.generic.CompareUtils;
|
|
|
|
|
-
|
|
|
|
|
-/**
|
|
|
|
|
- *
|
|
|
|
|
- * @author Ranides Atterwim <ranides@gmail.com>
|
|
|
|
|
- */
|
|
|
|
|
-public class CIndexTreeMap<V> extends AIndexMap<V> {
|
|
|
|
|
-
|
|
|
|
|
- private final Map<String, Comparator> name2sindex = new HashMap<>();
|
|
|
|
|
-
|
|
|
|
|
- private final Map<String, Function> name2mindex = new HashMap<>();
|
|
|
|
|
-
|
|
|
|
|
- private final Map<Comparator, RBTreeMultiSet<V>> cindexes = new HashMap<>();
|
|
|
|
|
-
|
|
|
|
|
- private final Map<Function, RBTreeMultiMap<Object, V>> mindexes = new HashMap<>();
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public IndexMap<V> index(String name, Comparator<V> index) {
|
|
|
|
|
- RBTreeMultiSet<V> set = new RBTreeMultiSet<>(index);
|
|
|
|
|
- cindexes.put(index, set);
|
|
|
|
|
- name2sindex.put(name, index);
|
|
|
|
|
- for(V item : values()) {
|
|
|
|
|
- set.add(item);
|
|
|
|
|
- }
|
|
|
|
|
- return this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public <T> IndexMap<V> index(String name, Function<V, T> index) {
|
|
|
|
|
- RBTreeMultiMap<Object,V> map = new RBTreeMultiMap<>();
|
|
|
|
|
- mindexes.put(index, map);
|
|
|
|
|
- name2mindex.put(name, index);
|
|
|
|
|
- for(V item : values()) {
|
|
|
|
|
- map.put(index.apply(item),item);
|
|
|
|
|
- }
|
|
|
|
|
- return this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
|
|
- @Override
|
|
|
|
|
- protected <T> Function<V, T> mindex(String name) {
|
|
|
|
|
- return name2mindex.get(name);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
|
|
- @Override
|
|
|
|
|
- protected Comparator<V> sindex(String name) {
|
|
|
|
|
- return name2sindex.get(name);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void remove(V value) {
|
|
|
|
|
- for(SortedSet<V> index : cindexes.values()) {
|
|
|
|
|
- CIndexTreeMap.this.iremove(index, value);
|
|
|
|
|
- }
|
|
|
|
|
- for(SortedMap<Object,V> index : mindexes.values()) {
|
|
|
|
|
- iremove(index, value);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void iremove(SortedSet<V> set, V value) {
|
|
|
|
|
- Comparator<? super V> c = set.comparator();
|
|
|
|
|
- Iterator<V> i = set.headSet(value).iterator();
|
|
|
|
|
- while(i.hasNext()) {
|
|
|
|
|
- V item = i.next();
|
|
|
|
|
- if(c.compare(item, value) !=0) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if(CompareUtils.equals(item,value)) {
|
|
|
|
|
- i.remove();
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private void iremove(SortedMap<Object,V> map, V value) {
|
|
|
|
|
- Comparator<Object> c = CompareUtils.comparator();
|
|
|
|
|
- Iterator<Entry<Object,V>> i = map.headMap(value).entrySet().iterator();
|
|
|
|
|
- while(i.hasNext()) {
|
|
|
|
|
- Entry<Object,V> item = i.next();
|
|
|
|
|
- if(c.compare(item.getKey(), value) !=0) {
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- if(CompareUtils.equals(item.getValue(),value)) {
|
|
|
|
|
- i.remove();
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
|
|
- @Override
|
|
|
|
|
- public void updateAll() {
|
|
|
|
|
- List<V> items = new ArrayList<>(values());
|
|
|
|
|
- for(SortedSet<V> index : cindexes.values()) {
|
|
|
|
|
- index.clear();
|
|
|
|
|
- index.addAll(items);
|
|
|
|
|
- }
|
|
|
|
|
- for(Entry<Function, RBTreeMultiMap<Object,V>> entry : mindexes.entrySet()) {
|
|
|
|
|
- Function fun = entry.getKey();
|
|
|
|
|
- RBTreeMultiMap<Object, V> index = entry.getValue();
|
|
|
|
|
- index.clear();
|
|
|
|
|
- for(V item : items) {
|
|
|
|
|
- index.put(fun.apply(item), item);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public AIndexQuery<V> find() {
|
|
|
|
|
- return new CHQuery();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
|
|
- @Override
|
|
|
|
|
- public void put(V value) {
|
|
|
|
|
- for(SortedSet<V> index : cindexes.values()) {
|
|
|
|
|
- index.add(value);
|
|
|
|
|
- }
|
|
|
|
|
- for(Entry<Function, RBTreeMultiMap<Object,V>> entry : mindexes.entrySet()) {
|
|
|
|
|
- Function fun = entry.getKey();
|
|
|
|
|
- RBTreeMultiMap<Object, V> index = entry.getValue();
|
|
|
|
|
- index.put(fun.apply(value), value);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void clear() {
|
|
|
|
|
- for(SortedSet<V> index : cindexes.values()) {
|
|
|
|
|
- index.clear();
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private Collection<V> values() {
|
|
|
|
|
- if(cindexes.isEmpty()) {
|
|
|
|
|
- return Collections.emptySet();
|
|
|
|
|
- }
|
|
|
|
|
- return cindexes.values().iterator().next();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private static Object after(ASortedMap<Object, ?> map, Object value) {
|
|
|
|
|
- Comparator<Object> cmp = CompareUtils.comparator();
|
|
|
|
|
- Iterator<Object> i = map.keySet().iterator(value);
|
|
|
|
|
- while(i.hasNext()) {
|
|
|
|
|
- Object next = i.next();
|
|
|
|
|
- if(cmp.compare(value, next)!=0) {
|
|
|
|
|
- return next;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private static <T> T after(ASortedSet<T> set, T value) {
|
|
|
|
|
- Comparator<? super T> cmp = set.comparator();
|
|
|
|
|
- Iterator<T> i = set.iterator(value);
|
|
|
|
|
- while(i.hasNext()) {
|
|
|
|
|
- T next = i.next();
|
|
|
|
|
- if(cmp.compare(value, next)!=0) {
|
|
|
|
|
- return next;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return null;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private final class CHQuery extends AIndexQuery<V> {
|
|
|
|
|
-
|
|
|
|
|
- private final List<Supplier<Collection<V>>> selectors;
|
|
|
|
|
-
|
|
|
|
|
- public CHQuery() {
|
|
|
|
|
- this.selectors = Collections.emptyList();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- public CHQuery(CHQuery query, Supplier<Collection<V>> selector) {
|
|
|
|
|
- this.selectors = new ArrayList<>(query.selectors.size()+1);
|
|
|
|
|
- this.selectors.addAll(query.selectors);
|
|
|
|
|
- this.selectors.add(selector);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- protected AIndexMap<V> parent() {
|
|
|
|
|
- return CIndexTreeMap.this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Stream<V> stream() {
|
|
|
|
|
- return select().stream();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public int size() {
|
|
|
|
|
- return select().size();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public Iterator<V> iterator() {
|
|
|
|
|
- return select().iterator();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public IndexQuery<V> eq(Comparator<V> index, V value) {
|
|
|
|
|
- return new CHQuery(this, () -> cindexes.get(index).getAll(value));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public <T> IndexQuery<V> eq(Function<V, T> index, T value) {
|
|
|
|
|
- return new CHQuery(this, () -> mindexes.get(index).getAll(value));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public IndexQuery<V> gt(Comparator<V> index, V value) {
|
|
|
|
|
- ASortedSet<V> set = cindexes.get(index);
|
|
|
|
|
- return new CHQuery(this, () -> {
|
|
|
|
|
- V last = after(set,value);
|
|
|
|
|
- return last==null ? Collections.emptyList() : set.tailSet(last);
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public <T> IndexQuery<V> gt(Function<V, T> index, T value) {
|
|
|
|
|
- RBTreeMultiMap<Object, V> map = mindexes.get(index);
|
|
|
|
|
- return new CHQuery(this, () -> {
|
|
|
|
|
- Object last = after(map,value);
|
|
|
|
|
- return last==null ? Collections.emptyList() : map.tailMap(last).values();
|
|
|
|
|
- });
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public IndexQuery<V> lt(Comparator<V> index, V value) {
|
|
|
|
|
- return new CHQuery(this, () -> cindexes.get(index).headSet(value));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public <T> IndexQuery<V> lt(Function<V, T> index, T value) {
|
|
|
|
|
- return new CHQuery(this, () -> mindexes.get(index).headMap(value).values());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public IndexQuery<V> in(Comparator<V> index, V begin, V end) {
|
|
|
|
|
- return new CHQuery(this, () -> cindexes.get(index).subSet(begin, end));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public <T> IndexQuery<V> in(Function<V, T> index, T begin, T end) {
|
|
|
|
|
- return new CHQuery(this, () -> mindexes.get(index).subMap(begin, end).values());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- public void remove() {
|
|
|
|
|
- removeAll(select());
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- @Override
|
|
|
|
|
- protected Collection<V> select() {
|
|
|
|
|
- int psize = 0;
|
|
|
|
|
- Collection<V> prim = null;
|
|
|
|
|
- List<Collection<V>> sec = new ArrayList<>(selectors.size()-1);
|
|
|
|
|
- for(Supplier<Collection<V>> s : selectors) {
|
|
|
|
|
- Collection<V> c = s.get();
|
|
|
|
|
- int csize = c.size();
|
|
|
|
|
-
|
|
|
|
|
- if(psize > csize) {
|
|
|
|
|
- sec.add(prim);
|
|
|
|
|
- prim = null;
|
|
|
|
|
- }
|
|
|
|
|
- if(prim==null) {
|
|
|
|
|
- prim = c;
|
|
|
|
|
- psize = csize;
|
|
|
|
|
- } else {
|
|
|
|
|
- sec.add(c);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- if(prim==null) {
|
|
|
|
|
- return Collections.emptyList();
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- List<V> out = new ArrayList<>(prim.size());
|
|
|
|
|
- for(V item : prim) {
|
|
|
|
|
- if(selected(sec,item)) {
|
|
|
|
|
- out.add(item);
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return out;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- private boolean selected(List<Collection<V>> sec, V item) {
|
|
|
|
|
- for(Collection<V> s : sec) {
|
|
|
|
|
- if(!s.contains(item)) {
|
|
|
|
|
- return false;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- return true;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
-}
|
|
|