C#难民寻求Java集合帮助

8

我需要将键/值信息存储在某种类型的集合中。在C#中,我会像这样定义一个字典:

var entries = new Dictionary<string, int>();
entries.Add("Stop me", 11);
entries.Add("Feed me", 12);
entries.Add("Walk me", 13);

然后我会这样访问这些值:
int value = entries["Stop me"];

我该如何在Java中做这个?我看到了使用ArrayList的示例,但如果可能的话,我想要使用泛型来解决问题。


1
C#难民?那不是一种罪恶状态吗?:)) - Mehrdad Afshari
更像是顿悟 :) - skaffman
ArrayList 是一种类似于序列或列表的结构(不是字典),尽管它是泛型的。 - oxbow_lakes
6个回答

22

你想要使用一个Map

Map<String, Integer> m = new HashMap<String, Integer>();
m.put("Stop me", 11);
Integer i = m.get("Stop me"); // i == 11

注意最后一行,我也可以这样说:

int i = m.get("Stop me");

这是Java中的缩写,使用自动拆箱:

int i = m.get("Stop me").intValue()
如果在给定的键中没有值,get方法返回null,并且该表达式会抛出一个NullPointerException异常。因此,在这种情况下使用包装类型Integer总是一个好主意。

7

使用java.util.Map。有几种实现方式:

  • HashMap:O(1)查找,不维护键的顺序
  • TreeMap:O(log n)查找,维护键的顺序,因此可以按照保证的顺序迭代它们
  • LinkedHashMap:O(1)查找,按照添加到映射中的顺序迭代键。

您可以像这样使用它们:

Map<String,Integer> map = new HashMap<String,Integer>();
map.put("Stop me", 11);
map.put("Feed me", 12);

int value = map.get("Stop me");

在与集合相关的工作中,为了方便起见,请查看Google Collections库。它非常棒。


重复评论:你最后一行很危险:如果在映射中没有该键的值,由于你使用了拆箱操作,它将抛出NullPointerException异常。 - oxbow_lakes
地图中有该键的值!但是为了澄清,您首先应该通过调用地图的contains方法和/或检查get(key)的结果不为null来检查缺少的键。后者不太可能发生,因为在对象之间传递空值是不好的做法。 - Nat
糟糕,我的意思是“nulls”而不是“mulls”。 - Nat
如果O的写法正确的话,Map解释应该会值得加上+1。HashMap和LinkedHashMap可提供常数时间(O(1))性能,而不是O(n)。它们的最坏情况性能(即所有对象具有相同哈希值)为O(n)。 - oxbow_lakes
我意识到我打错了,发现你已经在纠正之前赶上了我! - Nat

6

在Java中,您使用Map

请注意,您不能将int(或任何其他原始类型)用作通用类型参数,但由于自动装箱,它仍然表现得几乎像是Map<String,int>而不是Map<String,Integer>。(但是,在性能敏感的代码中不要进行大量的自动装箱。)

Map<String, Integer> entries = new HashMap<String, Integer>();
entries.put("Stop me", 11);
entries.put("Feed me", 12);
entries.put("Walk me", 13);
int value = entries.get("Stop me"); // if you know it exists
// If you're not sure whether the map contains a value, it's better to do:
Integer boxedValue = entries.get("Punch me");
if (boxedValue != null) {
    int unboxedValue = boxedValue;
    ...
}

你的最后一行代码很危险:如果映射表中没有该键对应的值,由于使用了自动拆箱,它会抛出NullPointerException异常。 - oxbow_lakes
是的,说得好。自动装箱很不错,但拆箱并没有太大帮助。 - Michael Myers
继续使用 @NotNull 注解。 - oxbow_lakes

2

看起来你正在寻找类似于HashMap的东西。


1
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("Stop Me", 11);
map.put("Feed Me", 12);
map.put("Walk Me", 13);
Integer x; // little hack
int value = (x = a.get("aaa")) == null? 0 : x;

作为替代方案,您可以尝试枚举:

enum Action {

    STOP(11),
    FEED(12),
    WALK(13);

    private final int value;

    private Action(int value) {
        this.value = value;
    }

    public int value() {
        return value;
    }

    public static Action valueOf(int value) {
        for (Action action : values()) {
            if (action.value == value) {
                return action;
            }
        }

        return null; // or a null-object
    }
}

测试:

public void action() {
    Action action = Action.valueOf("FEED"); 
    // or Action.FEED for more compile-time safety
    int value = action.value();
    // instantiating by code 
    Action walk = Action.valueOf(13);
}

1
重复评论:你的最后一行很危险:如果在该键处的映射中没有值,由于你使用了拆箱,它将抛出NullPointerException异常。 - oxbow_lakes
希望用户的名称是合法的Java标识符。 - akarnokd
拥有一个空值作为一种值的枚举并不真正是一个枚举。枚举应该列举出可能的值。 - oxbow_lakes

1
你肯定需要一个 HashMap,它是 Java 版本的 C# Dictionary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接