实现映射和保持插入顺序的Java类?

我在java中寻找一个类,具有键值关联,但不使用哈希。以下是我目前正在做的事情:

  1. Hashtable添加值。
  2. 获取Hashtable.entrySet()的迭代器。
  3. 遍历所有值并且:
    1. 为迭代器获取一个Map.Entry
    2. 基于该值创建一个Module类型的对象(自定义类)。
    3. 将类添加到JPanel中。
    4. 李< / ol > < / >
    5. 显示面板。

    这样做的问题是,我无法控制返回值的顺序,因此不能以给定的顺序显示值(没有对顺序进行硬编码)。

    我会为此使用ArrayListVector,但在代码后面,我需要为给定的键抓取Module对象,而我不能使用ArrayListVector

    有人知道有免费/开源的Java类可以做到这一点吗?或者有一种方法可以根据添加的时间从Hashtable中获取值吗?

    谢谢!

368924 次浏览

我建议LinkedHashMapTreeMapLinkedHashMap按插入的顺序保存键,而TreeMap通过Comparator或自然的Comparable顺序保存键。

因为它不需要保持元素排序,LinkedHashMap在大多数情况下应该更快;根据Javadocs, TreeMap对于containsKeygetputremove具有O(log n)的性能,而LinkedHashMap对于每个都具有O(1)的性能。

如果您的API只期望可预测的排序顺序,而不是特定的排序顺序,请考虑使用这两个类实现的接口NavigableMapSortedMap。这将允许您不会将特定的实现泄漏到您的API中,然后随意切换到这些特定的类或完全不同的实现。

我不知道它是否是开源的,但在谷歌了一下之后,我找到了这个Map的实现使用数组列表。它似乎是1.5之前的Java,所以您可能想要泛化它,这应该很容易。注意,这个实现有O(N)访问权限,但如果您没有向JPanel添加数百个小部件,这应该不是问题,无论如何也不应该这样做。

您可以维护Map(用于快速查找)和List(用于顺序),但LinkedHashMap可能是最简单的。你也可以尝试SortedMap,例如TreeMap,它可以有你指定的任何顺序。

如果一个不可变的映射符合您的需求则谷歌有一个名为番石榴的库(也参见番石榴的问题)

番石榴提供了一个具有可靠的用户指定迭代顺序的ImmutableMap。这个ImmutableMap对于containsKey, get有O(1)性能。显然不支持放置和移除。

ImmutableMap对象是通过使用优雅的静态方便方法的()copyOf ()构建器对象构造的。

当你遍历映射的keySet(), entrySet()或values()时,LinkedHashMap将按它们插入到映射中的顺序返回元素。

Map<String, String> map = new LinkedHashMap<String, String>();


map.put("id", "1");
map.put("name", "rohan");
map.put("age", "26");


for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}

这将按元素放入map中的顺序打印它们:

id = 1
name = rohan
age = 26

每当我需要保持事物的自然顺序时,我就使用EnumMap

键将是枚举,你可以插入任何你想要的顺序,但当你迭代它将迭代在枚举顺序(自然顺序)。

此外,在使用EnumMap时,不应该有碰撞,这可以更有效。

我真的发现使用enumMap使代码干净易读。 这里是例子

你可以使用LinkedHashMap来确定Map中的插入顺序

关于Java LinkedHashMap类的要点是:

  1. 只包含唯一的元素。

  2. LinkedHashMap包含基于键的值。

  3. 可以有一个空键和多个空值。

  4. 它与HashMap相同,只是维持插入顺序

    public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
    

但是如果你想使用用户定义对象或任何原始数据类型键来排序map中的值,那么你应该使用TreeMap

你可以使用LinkedHashMap<K, V>,也可以实现你自己的CustomMap,它维护插入顺序。

您可以使用以下CustomHashMap与以下功能:

  • 插入顺序是通过内部使用LinkedHashMap来维护的。
  • 不允许使用null或空字符串的键。
  • 一旦key with value被创建,我们就不会重写它的值。

HashMap vs LinkedHashMap vs CustomHashMap

interface CustomMap<K, V> extends Map<K, V> {
public boolean insertionRule(K key, V value);
}


@SuppressWarnings({ "rawtypes", "unchecked" })
public class CustomHashMap<K, V> implements CustomMap<K, V> {
private Map<K, V> entryMap;
// SET: Adds the specified element to this set if it is not already present.
private Set<K> entrySet;


public CustomHashMap() {
super();
entryMap = new LinkedHashMap<K, V>();
entrySet = new HashSet();
}


@Override
public boolean insertionRule(K key, V value) {
// KEY as null and EMPTY String is not allowed.
if (key == null || (key instanceof String && ((String) key).trim().equals("") ) ) {
return false;
}


// If key already available then, we are not overriding its value.
if (entrySet.contains(key)) { // Then override its value, but we are not allowing
return false;
} else { // Add the entry
entrySet.add(key);
entryMap.put(key, value);
return true;
}
}
public V put(K key, V value) {
V oldValue = entryMap.get(key);
insertionRule(key, value);
return oldValue;
}
public void putAll(Map<? extends K, ? extends V> t) {
for (Iterator i = t.keySet().iterator(); i.hasNext();) {
K key = (K) i.next();
insertionRule(key, t.get(key));
}
}


public void clear() {
entryMap.clear();
entrySet.clear();
}
public boolean containsKey(Object key) {
return entryMap.containsKey(key);
}
public boolean containsValue(Object value) {
return entryMap.containsValue(value);
}
public Set entrySet() {
return entryMap.entrySet();
}
public boolean equals(Object o) {
return entryMap.equals(o);
}
public V get(Object key) {
return entryMap.get(key);
}
public int hashCode() {
return entryMap.hashCode();
}
public boolean isEmpty() {
return entryMap.isEmpty();
}
public Set keySet() {
return entrySet;
}
public V remove(Object key) {
entrySet.remove(key);
return entryMap.remove(key);
}
public int size() {
return entryMap.size();
}
public Collection values() {
return entryMap.values();
}
}

使用CustomHashMap:

public static void main(String[] args) {
System.out.println("== LinkedHashMap ==");
Map<Object, String> map2 = new LinkedHashMap<Object, String>();
addData(map2);


System.out.println("== CustomHashMap ==");
Map<Object, String> map = new CustomHashMap<Object, String>();
addData(map);
}
public static void addData(Map<Object, String> map) {
map.put(null, "1");
map.put("name", "Yash");
map.put("1", "1 - Str");
map.put("1", "2 - Str"); // Overriding value
map.put("", "1"); // Empty String
map.put(" ", "1"); // Empty String
map.put(1, "Int");
map.put(null, "2"); // Null


for (Map.Entry<Object, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}

O / P:

== LinkedHashMap == | == CustomHashMap ==
null = 2            | name = Yash
name = Yash         | 1 = 1 - Str
1 = 2 - Str         | 1 = Int
= 1                |
= 1               |
1 = Int             |

如果你知道KEY是固定的,那么你可以使用EnumMap。从属性/XML文件中获取值

例:

enum ORACLE {
IP, URL, USER_NAME, PASSWORD, DB_Name;
}


EnumMap<ORACLE, String> props = new EnumMap<ORACLE, String>(ORACLE.class);
props.put(ORACLE.IP, "127.0.0.1");
props.put(ORACLE.URL, "...");
props.put(ORACLE.USER_NAME, "Scott");
props.put(ORACLE.PASSWORD, "Tiget");
props.put(ORACLE.DB_Name, "MyDB");