Использовал Multikey(1,2,3) для хранения записей на карте. Теперь только есть (1) . Могу ли я получить все записи, которые имеют (1) в Multikeys?
Я вставил значения в карту, используя Multikey с 3 параметрами. Теперь я хотел бы получить все записи, которые имеют определенный ключ в их Multikey - и я не имею представления о значениях других 2 ..
map.put(new MultiKey(valueA,valueB,valueC), value);
Теперь есть только значение A, мне нужно получить значение
Если требуется разъяснение, пожалуйста, спросите, и я уточню, а не голосование, чтобы закрыть.. Спасибо:)
..
2 ответа
Что-то простое, как
static <V> List<V> getValues(Map<MultiKey, V> map, Object key1) {
List<V> values = new ArrayList<>();
for (Map.Entry<MultiKey, V> entry : map.entrySet()) {
MultiKey key = entry.getKey();
if (key.getKey(0).equals(key1)) {
values.add(entry.getValue());
}
}
return values;
}
может работать просто отлично. Расширение использования нескольких (key1, key2, ...) оставлено читателю в качестве упражнения.
Я на самом деле создал класс только для этого.
public class MultiMap<K, V> {
private final HashMap<KeySet<K>, V> model = new HashMap<>();
public MultiMap() {}
public V add(V value, K first, K... keys) {
return model.put(new KeySet<>(first, keys));
}
public V add(V value, Set<K> keys){
return model.get(new KeySet<>(keys));
}
public Set<V> getIncludingSubsets(K... keys){
HashSet<V> all = new HashSet<>();
for (Entry<KeySet<K>, V> entry : model.entrySet()) {
if (entry.getKey().containsPartially(keys)) {
all.add(entry.getValue());
}
}
return all;
}
public Set<V> getIncludingSubsets(Set<K> keys){
HashSet<V> all = new HashSet<>();
for (Entry<KeySet<K>, V> entry : model.entrySet()) {
if (entry.getKey().containsPartially(keys)) {
all.add(entry.getValue());
}
}
return all;
}
public void clear(){
model.clear();
}
private class KeySet<T> extends HashSet<T>{
private KeySet(T first, T ... rest){
super();
add(first);
for (T object : rest) {
add(object);
}
}
private KeySet(Collection<T> data){
super(data);
}
@Override
public int hashCode() {
int hash = 5;
for (T value : this) {
hash = 41 * hash + Objects.hashCode(value);
}
return hash;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final KeySet<?> other = (KeySet<?>) obj;
return hashCode() == other.hashCode();
}
public boolean containsPartially(T... values){
for (T value : values) {
if (!contains(value)) {
return false;
}
}
return true;
}
public boolean containsPartially(Set<T> values){
for (T value : values) {
if (!contains(value)) {
return false;
}
}
return true;
}
}
}
Вот пример кода, иллюстрирующий, как это работает:
MultiMap<String, String> mm = new MultiMap<>();
// "A","B","C" -> v1
// "A","B" -> v2
// "A","C" -> v3
mm.add("v1", "A", "B", "C");
mm.add("v2", "A", "B");
mm.add("v3", "A", "C");
System.out.println(mm.getIncludingSubsets("A", "C"));
System.out.println(mm.getIncludingSubsets("B"));
System.out.println(mm.getIncludingSubsets("C"));
System.out.println(mm.getIncludingSubsets("C", "B", "A"));
System.out.println(mm.getIncludingSubsets("B", "A"));
System.out.println(mm.getIncludingSubsets("B", "C"));
Это даст:
[v1, v3]
[v1, v2]
[v1, v3]
[v1]
[v1, v2]
[v1]
Я уверен, что с небольшим творческим потенциалом вы можете изменить эту реализацию, чтобы она расширяла HashMap
вместо того, чтобы иметь один в качестве поля.