Description
The following implementation sketch of NameSet and friends is simpler in terms of code readability:
public abstract class CaseInsensitiveKey { public final String value; public CaseInsensitiveKey(String value) { this.value = value; } @Override public String toString() { return value; } public abstract int compareResult(); }
public final class CaseInsensitiveLowerKey extends CaseInsensitiveKey { public CaseInsensitiveLowerKey(String value) { super(value); } @Override public int compareResult() { return -1; } }
public final class CaseInsensitiveUpperKey extends CaseInsensitiveKey { public CaseInsensitiveUpperKey(String value) { super(value); } @Override public int compareResult() { return 1; } }
public class NameMap2<V> { /** * Comparator that compares all strings differently, but if two strings are * equal in case-insensitive match they are right next to each other. In a * collection sorted on this comparator, we can find case-insensitive matches * for a given string using a range scan between the upper-case string and * the lower-case string. */ public static final Comparator<Object> COMPARATOR = (o1, o2) -> { String s1 = o1.toString(); String s2 = o2.toString(); int c = s1.compareToIgnoreCase(s2); if (c != 0) { return c; } if (o1 instanceof CaseInsensitiveKey) { return ((CaseInsensitiveKey) o1).compareResult(); } if (o2 instanceof CaseInsensitiveKey) { return -((CaseInsensitiveKey) o2).compareResult(); } return s1.compareTo(s2); }; private final NavigableMap<String, V> map = new TreeMap<>(COMPARATOR); public void put(String name, V v) { map.put(name, v); } public NavigableMap<String, V> map() { return map; } private NavigableMap<Object, V> rawMap() { return (NavigableMap<Object, V>) (NavigableMap) map; } /** * Returns a map containing all the entries in the map that match the given * name. If case-sensitive, that map will have 0 or 1 elements; if * case-insensitive, it may have 0 or more. */ public NavigableMap<String, V> range(String name, boolean caseSensitive) { if (caseSensitive) { return map.subMap(name, true, name, true); } else { return (NavigableMap<String, V>) (NavigableMap) rawMap() .subMap(new CaseInsensitiveLowerKey(name), new CaseInsensitiveUpperKey(name)); } } /** * Returns whether this map contains a given key, with a given * case-sensitivity. */ public boolean containsKey(String name, boolean caseSensitive) { if (caseSensitive) { return map.subMap(name, true, name, true); } return (NavigableMap<String, V>) (NavigableMap) rawMap() .subMap(new CaseInsensitiveLowerKey(name), new CaseInsensitiveUpperKey(name)); } public Set<String> keySet() { return map.keySet(); } }
public class NameSet2 { NameMap2<Boolean> map = new NameMap2<>(); public void add(String s) { map.put(s, true); } public boolean contains(String name, boolean caseSensitive) { return map.containsKey(name, caseSensitive); } public Collection<String> range(String name, boolean caseSensitive) { return map.range(name, caseSensitive).keySet(); } public Iterable<String> iterable() { return Collections.unmodifiableSet(map.keySet()); } @Override public String toString() { return map.keySet().toString(); } }
Attachments
Issue Links
- is a clone of
-
CALCITE-2481 NameSet assumes lowercase characters have greater codes, which does not hold for certain characters
- Closed