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; } } }