HashMap с проблемой StringKey? - PullRequest
       11

HashMap с проблемой StringKey?

0 голосов
/ 07 декабря 2009

У меня есть список объектов 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 ]

3 голосов
/ 07 декабря 2009

Это код, который вам нужен:

    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 голос
/ 07 декабря 2009

Хммм ... если 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, если любой из них равен.

Edit: так как это HashSet, вы также должны реализовать hashCode(). Черт возьми, вы всегда должны использовать hashCode(), если вы все равно переопределяете equals.

0 голосов
/ 07 декабря 2009

HashMap использует метод .equals () для ключевого объекта.

0 голосов
/ 07 декабря 2009

В чем именно проблема? Код добавляет Foo, если он не встречался ранее, и вызывает действие на Foo, если он встречался ранее. Что вы ожидали от этого?

Чтобы ответить на ваш вопрос в конце, HashMap использует методы hashCode и equals ключевых объектов.

ОБНОВЛЕНИЕ : Вы пытаетесь вызвать doSomeThing только при повторных Foo с? Если свойство name Foo определяет его идентичность (и вы правильно реализовали hashCode() и equals()), вам следует использовать R. Раствор Бемроуза . Если name является , а не уникальным свойством Foo с, может помочь следующий код:

final Map<String, Foo> firstFooByName = new HashMap<String, Foo>();
final List<String> dupeNames = new ArrayList<String>();
for (final Foo foo: myFoos) {
    final String fooName = foo.getName();
    if (!firstFooByName.containsKey(fooName)) {
        firstFooByName.add(fooName)
    } else {
        dupeNames.add(fooName);
    }
}

for (final String fooName : dupeNames) {
    firstFooByName.get(fooName).doSomeThing();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...