带StringKey的HashMap问题?

时间:2009-12-07 17:46:24

标签: java hashmap

我有一个Foo对象列表。如果名称多次出现,我想对具有该名称的第一个项目执行某些操作。

HashMap<String, Foo> map = new HashMap<String, Foo>();
for (Foo bar: this.FooList)
{
    if (!map.containsKey(bar.getName()))
    {
        map.put(bar.getName(), bar);
    }
    else
    {
        map.get(bar.getName()).doSomeThing();
    }
}

但是这不起作用,因为每个名称(唯一的或不是唯一的)都会被抛出。 HashMap是否仅检查引用相等性而不检查关键对象上的相等性?

4 个答案:

答案 0 :(得分:3)

这是您需要的代码:

    HashMap<String, Foo> map = new HashMap<String, Foo>();
    for (Foo bar: this.FooList)
    {
        if (!map.containsKey(bar.getName()))
        {
            map.put(bar.getName(), bar);
        }
        else
        {
            Foo foo = map.get(bar.getName());
            if (foo != null)
                foo.doSomeThing();
            map.put(bar.getName(), null);
        }
    }

这是一个测试床:

import java.util.HashMap;
import java.util.ArrayList;

public class Example
{
    public static void main(String[] args)
    {
        new Example().run();
    }

    private ArrayList<Foo> FooList = new ArrayList<Foo>();

    public void run()
    {
        FooList.add(new Foo("abc", 1));
        FooList.add(new Foo("abc", 2));
        FooList.add(new Foo("def", 3));
        FooList.add(new Foo("abc", 4));
        FooList.add(new Foo("abc", 5));
        FooList.add(new Foo("ghi", 6));
        FooList.add(new Foo("def", 7));

        HashMap<String, Foo> map = new HashMap<String, Foo>();
        for (Foo bar: this.FooList)
        {
            if (!map.containsKey(bar.getName()))
            {
                map.put(bar.getName(), bar);
            }
            else
            {
                Foo foo = map.get(bar.getName());
                if (foo != null)
                    foo.doSomeThing();
                map.put(bar.getName(), null);
            }
        }
    }

    class Foo
    {
        public Foo(String name, int i)
        {
            this.name = name;
            this.i = i;
        }

        public String getName()
        {
            return name;
        }

        public void doSomeThing()
        {
            System.out.println(getName() + " " + i);
        }

        private String name;
        private int i;
    }
}

输出是:

abc 1
def 3

答案 1 :(得分:1)

嗯...如果Foo实现equals()以便它只检查名称,你总是可以这样做:

Set<Foo> set = new HashSet<Foo>();
for (Foo bar: this.FooList)
{
    if (!set.add(bar)) {
       bar.doSomething();
    }
}

哪个有效,因为set.add(bar)将针对集合中已有的每个元素运行bar.equals,如果其中任何元素相等则返回false。

编辑:由于这是一个HashSet,您还应该实现hashCode()。哎呀,如果你无论如何都要覆盖hashCode(),你应该始终实施equals

答案 2 :(得分:0)

究竟是什么问题?如果以前没有遇到过,则代码会添加Foo,如果之前遇到过,则会在Foo上调用操作。你有什么期望呢?

要在最后回答您的问题,HashMap依赖于关键对象的hashCodeequals方法。

更新:您是否尝试仅在重复的doSomeThing上调用Foo ?如果name的{​​{1}}属性定义了它的身份(并且您正确实施了FoohashCode()),则应使用R. Bemrose's solution。如果equals() name的唯一属性,则以下代码可能有所帮助:

Foo

答案 3 :(得分:0)

HashMap在密钥对象上使用.equals()方法。