我正在寻找具有键-值关联但不使用哈希的Java类。 这是我目前正在做的事情:
- 将值添加到
Hashtable
。 - 获取
Hashtable.entrySet()
的迭代器。 - 遍历所有值和:
- 获取迭代器的
Map.Entry
。 - 根据该值创建类型为
Module
(自定义类)的对象。 - 将类添加到JPanel。
- 获取迭代器的
- 显示面板。
这样做的问题是我无法控制获取值的顺序,因此无法按给定顺序显示值(没有对顺序进行硬编码)。
我将为此使用ArrayList
或Vector
,但是稍后在代码中,我需要获取给定Key的Module
对象,而ArrayList
或Vector
无法做到这一点。
有谁知道一个免费的/开源的Java类可以做到这一点,还是一种基于值何时从Hashtable
获取值的方法?
谢谢!
#1楼
您可以尝试我的链接树图实现。
#2楼
如果一幅不变的地图符合您的需求,那么Google就有一个名为guava的图书馆(另请参阅guava问题 )
Guava提供了具有可靠的用户指定迭代顺序的ImmutableMap 。 该ImmutableMap对containsKey get具有O(1)性能。 显然不支持放置和删除。
ImmutableMap对象是使用优雅的静态便利方法of()和copyOf()或Builder对象构造的。
#3楼
当您遍历地图的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());
}
这将按照将元素放入地图的顺序进行打印:
id = 1
name = rohan
age = 26
#4楼
每当我需要保持事物的自然顺序时,我都会使用EnumMap
键将是枚举,您可以按所需的任何顺序插入,但是当您进行迭代时,它将以枚举顺序(自然顺序)进行迭代。
同样,在使用EnumMap时,不应存在任何会更有效的冲突。
我真的发现使用enumMap可以使代码清晰可读。 这是一个例子
#5楼
您可以使用LinkedHashMap来映射Map中的主要插入顺序
关于Java LinkedHashMap类的要点是:
- 它仅包含唯一元素。
LinkedHashMap包含基于键3的值。它可以具有一个null键和多个null值。 4,与HashMap相同,但保持插入顺序
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V>
但是,如果要使用用户定义的对象或任何原始数据类型键在地图中对值进行排序,则应使用TreeMap。有关更多信息,请参考此链接
#6楼
您可以使用LinkedHashMap<K, V>
,也可以实现自己的CustomMap ,以维护插入顺序。
您可以将以下CustomHashMap
与以下功能一起使用:
- 通过内部使用LinkedHashMap可以维护插入顺序。
- 用钥匙
null
或空字符串是不允许的。 - 创建具有值的键后,我们不会覆盖其值。
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");
#7楼
我建议使用LinkedHashMap
或TreeMap
。 LinkedHashMap
保留键的插入顺序,而TreeMap
则通过Comparator
或元素的自然Comparable
顺序进行排序。
由于不必对元素进行排序,因此在大多数情况下, LinkedHashMap
应该更快。 根据Javadocs, TreeMap
的containsKey
, get
, put
和remove
性能为O(log n)
,而LinkedHashMap
的每种性能均为O(1)
。
如果您的API仅期望可预测的排序顺序,而不是特定的排序顺序,请考虑使用这两个类实现的接口NavigableMap
或SortedMap
。 这样一来,您就不会将特定的实现泄漏到您的API中,之后便可以随意切换到这些特定的类或完全不同的实现。
#8楼
我不知道它是否是开源的,但是经过一番谷歌搜索之后,我发现了使用ArrayList的Map实现 。 它似乎是Java 1.5之前的版本,因此您可能希望对其进行泛化,这应该很容易。 请注意,此实现具有O(N)访问权限,但是如果您不向JPanel添加数百个小部件,这也不是问题,无论如何都不应该这样做。
#9楼
您可以维护一个Map
(用于快速查找)和List
(用于顺序),但LinkedHashMap
可能是最简单的。 您也可以尝试使用SortedMap
例如TreeMap
,它具有您指定的任何顺序。