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

org.jboss.resteasy.reactive.server.mapping.SubstringMap Maven / Gradle / Ivy

There is a newer version: 3.17.5
Show newest version
package org.jboss.resteasy.reactive.server.mapping;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * A string keyed map that can be accessed as a substring, eliminating the need to allocate a new string
 * to do a key comparison against.
 * 

* This class uses linear probing and is thread safe due to copy on write semantics. As such it is not recomended * for data that changes frequently. *

* This class does not actually implement the map interface to avoid implementing unnecessary operations. * * @author Stuart Douglas */ class SubstringMap { private static final int ALL_BUT_LAST_BIT = ~1; private final Object[] table; private final int size; public SubstringMap(Object[] table, int size) { this.table = table; this.size = size; } int size() { return size; } SubstringMatch get(String key, int length) { return doGet(key, length); } SubstringMatch get(String key) { return doGet(key, key.length()); } private SubstringMatch doGet(String key, int length) { if (key.length() < length) { throw new IllegalArgumentException(); } Object[] table = this.table; int hash = hash(key, length); int pos = tablePos(table, hash); int start = pos; while (table[pos] != null) { if (doEquals((String) table[pos], key, length)) { return (SubstringMatch) table[pos + 1]; } pos += 2; if (pos >= table.length) { pos = 0; } if (pos == start) { return null; } } return null; } private static int tablePos(Object[] table, int hash) { return (hash & (table.length - 1)) & ALL_BUT_LAST_BIT; } private static int hash(String value, int length) { if (length == 0) { return 0; } int h = 0; for (int i = 0; i < length; i++) { h = 31 * h + value.charAt(i); } return h; } private boolean doEquals(String s1, String s2, int length) { if (s1.length() != length || s2.length() < length) { return false; } for (int i = 0; i < length; ++i) { if (s1.charAt(i) != s2.charAt(i)) { return false; } } return true; } Iterable keys() { return new Iterable() { @Override public Iterator iterator() { final Object[] tMap = table; int i = 0; while (i < table.length && tMap[i] == null) { i += 2; } final int startPos = i; return new Iterator() { private Object[] map = tMap; private int pos = startPos; @Override public boolean hasNext() { return pos < table.length; } @Override public String next() { if (!hasNext()) { throw new NoSuchElementException(); } String ret = (String) map[pos]; pos += 2; while (pos < table.length && tMap[pos] == null) { pos += 2; } return ret; } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }; } static class Builder { private Object[] table = new Object[16]; private int size; SubstringMap build() { return new SubstringMap<>(table, size); } void put(String key, V value) { if (key == null) { throw new NullPointerException(); } Object[] newTable; if (table.length / (double) size < 4 && table.length != Integer.MAX_VALUE) { newTable = new Object[table.length << 1]; for (int i = 0; i < table.length; i += 2) { if (table[i] != null) { doPut(newTable, (String) table[i], table[i + 1]); } } } else { newTable = new Object[table.length]; System.arraycopy(table, 0, newTable, 0, table.length); } doPut(newTable, key, new SubstringMap.SubstringMatch<>(key, value)); this.table = newTable; size++; } private void doPut(Object[] newTable, String key, Object value) { int hash = hash(key, key.length()); int pos = tablePos(newTable, hash); while (newTable[pos] != null && !newTable[pos].equals(key)) { pos += 2; if (pos >= newTable.length) { pos = 0; } } newTable[pos] = key; newTable[pos + 1] = value; } } public static final class SubstringMatch { private final String key; private final V value; public SubstringMatch(String key, V value) { this.key = key; this.value = value; } public String getKey() { return key; } public V getValue() { return value; } @Override public String toString() { return "SubstringMatch{ key: " + key + ", value: " + value + " }"; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy