planetiler/planetiler-core/src/main/java/com/onthegomap/planetiler/util/CommonStringEncoder.java

78 wiersze
2.2 KiB
Java
Czysty Zwykły widok Historia

package com.onthegomap.planetiler.util;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
2021-09-10 00:46:20 +00:00
import javax.annotation.concurrent.ThreadSafe;
2021-09-10 00:46:20 +00:00
/**
* A utility for compressing commonly-used strings (i.e. layer name, tag attributes).
2021-09-10 00:46:20 +00:00
*/
@ThreadSafe
public class CommonStringEncoder {
private final int maxStrings;
private final Map<String, Integer> stringToId;
private final String[] idToString;
private final AtomicInteger stringId = new AtomicInteger(0);
public CommonStringEncoder(int maxStrings) {
this.maxStrings = maxStrings;
stringToId = new ConcurrentHashMap<>(maxStrings);
idToString = new String[maxStrings];
}
2021-09-10 00:46:20 +00:00
/**
* Returns the string for {@code id}.
*
* @throws IllegalArgumentException if there is no value for {@code id}.
*/
public String decode(int id) {
String str = idToString[id];
if (str == null) {
2021-09-10 00:46:20 +00:00
throw new IllegalArgumentException("No string for " + id);
}
return str;
}
2021-09-10 00:46:20 +00:00
/**
* Returns a int value to each unique string passed in.
2021-09-10 00:46:20 +00:00
*
* @param string the string to store
* @return an int that can be converted back to a string by {@link #decode(int)}.
2021-09-10 00:46:20 +00:00
* @throws IllegalArgumentException if called for too many values
*/
public int encode(String string) {
2021-08-11 12:40:49 +00:00
// optimization to avoid more expensive computeIfAbsent call for the majority case when concurrent hash map already
// contains the value.
Integer result = stringToId.get(string);
2021-08-11 12:40:49 +00:00
if (result == null) {
result = stringToId.computeIfAbsent(string, s -> {
int id = stringId.getAndIncrement();
if (id >= maxStrings) {
throw new IllegalArgumentException("Too many strings");
2021-08-11 12:40:49 +00:00
}
2021-09-10 00:46:20 +00:00
idToString[id] = string;
return id;
2021-08-11 12:40:49 +00:00
});
}
return result;
}
/**
* Variant of CommonStringEncoder based on byte rather than int for string indexing.
*/
public static class AsByte {
private final CommonStringEncoder encoder = new CommonStringEncoder(256);
public String decode(byte id) {
return encoder.decode(id & 0xff);
}
public byte encode(String string) {
return (byte) encoder.encode(string);
}
}
}