Java Hashtable问题

时间:2009-12-29 20:13:44

标签: java hashtable

我在使用java哈希表时遇到了一些问题。以下是我的hastable键和值

{corpus \ 2.txt = [cat sparrow],corpus \ 4.txt = [elephant sparrow],corpus \ 1.txt = [elephant cow],corpus \ 3.txt = [cow cat]}

因此,如果我想访问第一个元组,我必须传递密钥“corpus \ 2.txt”来获取其值。如果我通过价值,我可以得到它的关键。但我想制作一个我传递的功能,如1 2 3 4等,同时获得关键和价值。有什么想法吗?

第二个问题: 是否可以存储具有键和值的索引?或者是否可以从现有哈希表中获取索引(0,1,2,3等)?

谢谢!

6 个答案:

答案 0 :(得分:3)

对于初学者,我会使用HashMap,而不是(现在过时的)HashTable。如果你这样做,那么你可以使用Map.Entry返回一个键/值对(根据你的第一个问题)。

您无法使用密钥轻松存储索引。您可能希望创建一个特殊的Key对象:

public class Key {
   private String name;
   private int index;
   ....
}

使用合适的equals() / hashCode()实施(如评论中所述)并将其用作HashMap中的关键字。您必须使用此密钥执行查找,从而使用当前基于String的密钥构造一个,但我不认为这是一个大问题。

答案 1 :(得分:0)

API中没有方法可以从Java哈希表中获取特定条目。您可以使用entrySet方法访问所有条目的集合,并对其进行迭代,您将获得所有键值对作为Map.Entry个对象。

哈希表完全无序。它们只是从键到值的映射,并没有任何明确的索引。如果迭代entrySet结果,则会有一个特定的顺序来处理条目,但是当您修改哈希表时,这也可能会发生变化。

答案 2 :(得分:0)

看看LinkedHashMap,一个保留输入排序的地图实现。

答案 3 :(得分:0)

而是使用Map<Integer, ValueObject>,其中ValueObject只是一个带有两个属性的自定义javabean类,例如filenamedescription

基本启动示例:

public class ValueObject {
    private String filename;
    private String description;

    public ValueObject() {
        // Always keep default constructor alive.
    }

    public ValueObject(String filename, String description) {
        this.filename = filename;
        this.description = description;
    }

    // Add/generate public getters and setters for filename and description.
}

您可以使用如下:

Map<Integer, ValueObject> map = new HashMap<Integer, ValueObject>();
map.put(1, new ValueObject("corpus1.txt", "elephant cow"));
map.put(2, new ValueObject("corpus2.txt", "cat sparrow"));
map.put(3, new ValueObject("corpus3.txt", "cow cat"));
map.put(4, new ValueObject("corpus4.txt", "elephant sparrow"));

ValueObject vo = map.get(1); // Returns VO with corpus1.txt and elephant cow.

答案 4 :(得分:0)

无法通过索引访问Map。但是,如果您真正想要做的是逐个访问地图中的键值对,您可以这样做:

for (Map.Entry<String, List<String>> nameAndWords: hashmap) {
    String name = nameAndWords.getKey();
    List<String> words = nameAndWords.getValue();
    // do your stuff here
}

如果您确实需要建立索引,可以通过将密钥保存在列表中来向地图添加外部订单,在编辑地图时必须更新该列表:

HashMap<String, List<String>> wordsByCorpus;
List<String> corpusNames;

public void addCorpus(String name, List<String> words) {
    List<String> oldValue = wordsByCorpus.put(name, words);
    if (oldValue == null) corpusNames.add(name);
}

public void removeCorpus(String name) {
    wordsByCorpus.remove(name);
    corpusNames.remove(name);
}

public Map.Entry<String, List<String>> getCorpus(int i) {
    String name = corpusNames.get(i);
    List<String> words = wordsByCorpus.get(name);
    return wordsByCorpus.new SimpleImmutableEntry(name, words); // 1.6 only!
}

答案 5 :(得分:0)

您要么使用LinkedHashMap,它允许您使用添加的顺序索引访问添加到地图的值。

或者你想使用2个HashMaps。一个用字符串值索引,另一个用于将整数值转换为第一个映射的字符串值键。然后很容易从索引获取键和值:

String key = mapByIntToStringKey.get(index);
V  value = mapByStringKey.get(key);
// now have both key and value, no linear searching so should be fast

因此,您的地图将包含: mapByStringKey = {corpus \ 2.txt = [cat sparrow],corpus \ 4.txt = [elephant sparrow],corpus \ 1.txt = [elephant cow],corpus \ 3.txt = [cow cat]}

mapByIntToStringKey {2 = corpus \ 2.txt,4 = corpus \ 4.txt,1 = corpus \ 1.txt}

虽然这假设您的所有密钥不仅仅是“语料库”+索引+“。txt”。

如果所有键都如上所述,那么如果索引不是稀疏的,那么你可以使用一个简单的ArrayList(前面提到的)并使用快速的get(index)(直接在数组中查找,不能快得多)比那个),然后使用上面的表达式重建字符串键。 如果索引是稀疏的(即一些缺失,则存在间隙),那么只需使用mapByIntToStringKey,但用mapByIntToValue替换,并使用先前的字符串表达式重构所需的任何字符串键。

当前的高回答对我来说似乎很奇怪,因为建议是仅使用复合键的int索引位来键入映射。除非我读错了,否则意味着你无法单独使用字符串键来查找地图中的值,或者只是意味着你总是可以从字符串键中推断出int索引。