package com.jpexs.decompiler.flash.amf.amf3;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
* Map which maintains order of keys
*
* @param <K> Key type
* @param <V> Value type
*/
public class ListMap<K, V> implements Map<K, V> {
private final Set<K> orderedKeys = new ListSet<>();
private final Map<K, V> map;
/**
* Creates new MaintainKeyOrderMap based on HashMap
*/
public ListMap() {
this(false);
}
/**
* Creates new MaintainKeyOrderMap
*
* @param useIdentityMap The HashMap will be based on IdentityHashMap
*/
public ListMap(boolean useIdentityMap) {
this(useIdentityMap, new HashMap<>());
}
/**
* Creates new MaintainKeyOrderMap based on HashMap
*
* @param m Initial items
*/
public ListMap(Map<? extends K, ? extends V> m) {
this(false, m);
}
/**
* Creates new MaintainKeyOrderMap
*
* @param useIdentityMap The HashMap will be based on IdentityHashMap
* @param m Initial items
*/
public ListMap(boolean useIdentityMap, Map<? extends K, ? extends V> m) {
if (useIdentityMap) {
map = new IdentityHashMap<>();
} else {
map = new HashMap<>();
}
putAll(m);
}
@Override
public int size() {
return map.size();
}
@Override
public boolean isEmpty() {
return map.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return map.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return map.containsValue(value);
}
@Override
public V get(Object key) {
return map.get(key);
}
@Override
public V put(K key, V value) {
orderedKeys.add(key);
return map.put(key, value);
}
@Override
public V remove(Object key) {
orderedKeys.remove(key);
return map.remove(key);
}
@Override
public void putAll(Map<? extends K, ? extends V> m) {
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
orderedKeys.add(e.getKey());
}
map.putAll(m);
}
@Override
public void clear() {
orderedKeys.clear();
map.clear();
}
@Override
public Set<K> keySet() {
return new ListSet<>(orderedKeys);
}
@Override
public Collection<V> values() {
List<V> vals = new ArrayList<>();
for (K key : orderedKeys) {
vals.add(map.get(key));
}
return vals;
}
@Override
public Set<Entry<K, V>> entrySet() {
Set<Entry<K, V>> ret = new ListSet<>();
for (K key : orderedKeys) {
V value = map.get(key);
ret.add(new MyEntry<>(key, value));
}
return ret;
}
public static class MyEntry<K, V> implements Entry<K, V> {
private K key;
private V value;
public MyEntry(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() {
return key;
}
@Override
public V getValue() {
return value;
}
@Override
public V setValue(V value) {
V oldValue = this.value;
this.value = value;
return oldValue;
}
@Override
public int hashCode() {
int hash = 5;
hash = 37 * hash + Objects.hashCode(this.key);
hash = 37 * hash + Objects.hashCode(this.value);
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final MyEntry<?, ?> other = (MyEntry<?, ?>) obj;
if (!Objects.equals(this.key, other.key)) {
return false;
}
if (!Objects.equals(this.value, other.value)) {
return false;
}
return true;
}
}
}