Reputation: 4405
I have 3 different Set
act as a cache and each serves for different reason. Additionally the keys are of different types e.g. Integer
, String
etc
I was thinking to create a wrapper class around this, but then I thought of just having them all as part of 1 hashmap and based on the key I can pick the proper Set
But I am not sure what is the proper way to do that.
I'd like to avoid something like:
private final Map<Integer, Set<Object>> cache = new HashMap<>();
public boolean exists(Integer type, Object key) {
return cache.get(type).contains(key);
}
public void addKey(Integer type, Object key) {
if(type == CACHE_1) {
Set<Object> set = cache.get(type);
if(set == null) {
set = new HashSet<>();
cache.put(type, set);
}
set.add(key);
}
}
Is there a way to make it more type specific?
Update
These can be called as:
addKey(CACHE_1, "foo");
addKey(CACHE_2, 123);
or
if(exists(CACHE_1, "foo")
if(exists(CACHE_2, 123)
Upvotes: 0
Views: 395
Reputation: 120848
I am not sure you will like this, but you could use a "heterogeneous container". For example, define the Key
of the Map
:
static class Key<T> {
private final Integer one;
private final String two;
private final Long three;
private final Class<T> cls;
private Key(Integer one, String two, Long three, Class<T> cls) {
this.one = one;
this.two = two;
this.three = three;
this.cls = cls;
}
public Class<T> getCls() {
return cls;
}
public static Key<Integer> ofInteger(Integer one){
return new Key<>(one, null, null, Integer.class);
}
public static Key<String> ofString(String two){
return new Key<>(null, two, null, String.class);
}
public static Key<Long> ofLong(Long three){
return new Key<>(null, null, three, Long.class);
}
@Override
public int hashCode() {
return Objects.hash(one, two, three);
}
// simplified for example purpose
public boolean equals(Object obj) {
Key<?> other = (Key<?>)obj;
return Objects.equals(this.one, other.one) &&
Objects.equals(this.two, other.two) &&
Objects.equals(this.three, other.three);
}
}
Then define the container:
static class Holder {
private static final Map<Key<?>, Set<Object>> CACHE = new HashMap<>();
public static <T> boolean exists(Key<?> type, T key) {
return CACHE.get(type).contains(key);
}
public static <T> void addKey(Key<T> type, T key) {
CACHE.computeIfAbsent(type, x -> new HashSet<>()).add(key);
}
public static <T> Set<T> byKey(Key<T> key) {
Set<Object> set = CACHE.get(key);
return Optional.ofNullable(set).orElse(Collections.emptySet()).stream().map(key.getCls()::cast).collect(Collectors.toSet());
}
}
And some usage:
public static void main(String[] args) {
Holder.addKey(Key.ofInteger(1), 11);
Holder.addKey(Key.ofInteger(1), 22);
Holder.addKey(Key.ofInteger(1), 33);
Set<Integer> setI = Holder.byKey(Key.ofInteger(1));
Holder.addKey(Key.ofString("1"), "11");
Holder.addKey(Key.ofString("2"), "22");
Holder.addKey(Key.ofString("3"), "33");
Set<String> setS = Holder.byKey(Key.ofString("1"));
System.out.println(setI);
System.out.println(setS);
}
Upvotes: 1