任何人都可以解释java HashMap的这种奇怪行为吗?

时间:2011-07-07 12:14:58

标签: java hashmap

我在Java中使用过HashMap但从未遇到过这种行为。我必须输入项目项目组。它们的定义如下面的代码片段所示。

public class Item {
    String id;
    float total;
}

public class ItemGroup {
    String keyword;
    int frequency;
    List<Item> items;
}

所以 ItemGroup 包含0 .. *项目。这些项目具有共同的关键字,并且关键字在系统中以某种频率出现。现在是有趣的部分,我有以下方法,给出一个项目列表创建一个组列表。

public static ItemGroup[] createGroups(Item[] items){
    HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
    String[] words;

    for (int i=0; i<items.length; i++){
        words = items[i].getId().split(REGEX);

        // Process keywords
        for (int j=0; j<words.length; j++){
            if (words[j].isEmpty()) break;

            ItemGroup group = groups.get(words[j]);
            if (group != null){
                group.incrementFrequency();
                group.getItems().add(items[i]);
            }else {
                group = EconomFactory.eINSTANCE.createItemGroup();
                group.setKeyword(words[j]);
                group.incrementFrequency();
                group.getItems().add(items[i]);
                groups.put(words[j], group);
            }
        }
    }

    return groups.values().toArray(new ItemGroup[0]);                       
}

奇怪的部分是将项目添加到项目组(行group.getItems()。add(items [i]);)。在重组期间,该团体以一种奇怪的方式丢失了它的物品。使用调试我可以看到该组在操作之后包含该项目,但是后面的项目,例如当返回方法的值时,所有组都丢失了它们的项目。

我试过了:

public static ItemGroup[] createGroups(Item[] items){
    HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
    String[] words;

    for (int i=0; i<items.length; i++){
        words = items[i].getId().split(REGEX);

        // Create a new item based on the current one in the list
        Item item = EconomFactory.eINSTANCE.createItem();
        item.setId(items[i].getId());
        item.setTotal(items[i].getTotal());

        // Process key words
        for (int j=0; j<words.length; j++){
            if (words[j].isEmpty()) break;

            ItemGroup group = groups.get(words[j]);
            if (group != null){
                group.incrementFrequency();
                group.getItems().add(item);
            }else {
                group = EconomFactory.eINSTANCE.createItemGroup();
                group.setKeyword(words[j]);
                group.incrementFrequency();
                group.getItems().add(item);
                groups.put(words[j], group);
            }
        }
    }

    return groups.values().toArray(new ItemGroup[0]);                       
}   

但得到了相同的结果。但是,以下解决方案可以正常工作。

public static ItemGroup[] createGroups(Item[] items){
    HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
    String[] words;

    for (int i=0; i<items.length; i++){
        words = items[i].getId().split(REGEX);

        // Process key words
        for (int j=0; j<words.length; j++){
            if (words[j].isEmpty()) break;

            // Create a new item based on the current one in the list
            Item item = EconomFactory.eINSTANCE.createItem();
            item.setId(items[i].getId());
            item.setTotal(items[i].getTotal());

            ItemGroup group = groups.get(words[j]);
            if (group != null){
                group.incrementFrequency();
                group.getItems().add(item);
            }else {
                group = EconomFactory.eINSTANCE.createItemGroup();
                group.setKeyword(words[j]);
                group.incrementFrequency();
                group.getItems().add(item);
                groups.put(words[j], group);
            }
        }
    }

    return groups.values().toArray(new ItemGroup[0]);                       
}

方法EconomFactory.eINSTANCE.createItemGroup()实现如下:

public ItemGroup createItemGroup() {
    ItemGroupImpl itemGroup = new ItemGroupImpl();
    return itemGroup;
}

其中ItemGroupImpl是ItemGroup的实现,e.i。它是ItemGroup的子类。这是因为我使用EMF(Eclipse Modeling Framework)。

任何人都可以解释这种行为(为什么ItemGroup对象丢失了他们的项目)?

以下是ItemGroup和ItemGroupImpl的代码。同样的方式查找Item和ItemImpl的代码。

public interface ItemGroup extends EObject {
String getKeyword();

void setKeyword(String value);

int getFrequency();

void setFrequency(int value);

EList<Item> getItems();

void incrementFrequency();
}

public class ItemGroupImpl extends EObjectImpl implements ItemGroup {

protected static final String KEYWORD_EDEFAULT = null;

protected String keyword = KEYWORD_EDEFAULT;

protected static final int FREQUENCY_EDEFAULT = 0;

protected int frequency = FREQUENCY_EDEFAULT;

protected EList<Item> items;

protected ItemGroupImpl() {
    super();
}

@Override
protected EClass eStaticClass() {
    return EconomPackage.Literals.ITEM_GROUP;
}

public String getKeyword() {
    return keyword;
}

public void setKeyword(String newKeyword) {
    String oldKeyword = keyword;
    keyword = newKeyword;
    if (eNotificationRequired())
        eNotify(new ENotificationImpl(this, Notification.SET,
            EconomPackage.ITEM_GROUP__KEYWORD, oldKeyword, keyword));
}

public int getFrequency() {
    return frequency;
}

public void setFrequency(int newFrequency) {
    int oldFrequency = frequency;
    frequency = newFrequency;
    if (eNotificationRequired())
        eNotify(new ENotificationImpl(this, Notification.SET, 
            EconomPackage.ITEM_GROUP__FREQUENCY, oldFrequency, frequency));
}

public EList<Item> getItems() {
    if (items == null) {
        items = new EObjectContainmentEList<Item>(Item.class, this, 
            EconomPackage.ITEM_GROUP__ITEMS);
    }
    return items;
}

public void incrementFrequency() {
    this.frequency = getFrequency() + 1;
}

@Override
public NotificationChain eInverseRemove(InternalEObject otherEnd, int featureID, 
            NotificationChain msgs) {
    switch (featureID) {
        case EconomPackage.ITEM_GROUP__ITEMS:
            return ((InternalEList<?>)getItems()).basicRemove(otherEnd,
             msgs);
    }
    return super.eInverseRemove(otherEnd, featureID, msgs);
}

@Override
public Object eGet(int featureID, boolean resolve, boolean coreType) {
    switch (featureID) {
        case EconomPackage.ITEM_GROUP__KEYWORD:
            return getKeyword();
        case EconomPackage.ITEM_GROUP__FREQUENCY:
            return getFrequency();
        case EconomPackage.ITEM_GROUP__ITEMS:
            return getItems();
    }
    return super.eGet(featureID, resolve, coreType);
}

@SuppressWarnings("unchecked")
@Override
public void eSet(int featureID, Object newValue) {
    switch (featureID) {
        case EconomPackage.ITEM_GROUP__KEYWORD:
            setKeyword((String)newValue);
            return;
        case EconomPackage.ITEM_GROUP__FREQUENCY:
            setFrequency((Integer)newValue);
            return;
        case EconomPackage.ITEM_GROUP__ITEMS:
            getItems().clear();
            getItems().addAll((Collection<? extends Item>)newValue);
            return;
    }
    super.eSet(featureID, newValue);
}

@Override
public void eUnset(int featureID) {
    switch (featureID) {
        case EconomPackage.ITEM_GROUP__KEYWORD:
            setKeyword(KEYWORD_EDEFAULT);
            return;
        case EconomPackage.ITEM_GROUP__FREQUENCY:
            setFrequency(FREQUENCY_EDEFAULT);
            return;
        case EconomPackage.ITEM_GROUP__ITEMS:
            getItems().clear();
            return;
    }
    super.eUnset(featureID);
}

@Override
public boolean eIsSet(int featureID) {
    switch (featureID) {
        case EconomPackage.ITEM_GROUP__KEYWORD:
            return KEYWORD_EDEFAULT == null ? keyword != null : 
            !KEYWORD_EDEFAULT.equals(keyword);
        case EconomPackage.ITEM_GROUP__FREQUENCY:
            return frequency != FREQUENCY_EDEFAULT;
        case EconomPackage.ITEM_GROUP__ITEMS:
            return items != null && !items.isEmpty();
    }
    return super.eIsSet(featureID);
}

@Override
public String toString() {
    if (eIsProxy()) return super.toString();

    StringBuffer result = new StringBuffer();
    result.append("(keyword: ");
    result.append(keyword);
    result.append(", frequency: ");
    result.append(frequency);
    result.append(')');
    return result.toString();
}
}

2 个答案:

答案 0 :(得分:0)

在你的第二套代码中,我在哪里进行了初始化?

 public static ItemGroup[] createGroups(Item[] items){    
  HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>(); 
    String[] words; 
     // Create a new item based on the current one in the list
     Item item = EconomFactory.eINSTANCE.createItem();
     item.setId(items[i].getId());
     item.setTotal(items[i].getTotal()); 

变量i尚未在此上下文中初始化,因此它可以是任何值(因为它没有爆炸,我假设你的代码中有一个全局的“i”,而你正在用它开始你的方法值instaed为0.

在您正在运行的代码中,您在访问它之前已在方法中进行了初始化:

   public static ItemGroup[] createGroups(Item[] items){
     HashMap<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
     String[] words;
      for (int i=0; i<items.length; i++){ 
        words = items[i].getId().split(REGEX);
          // Process key words  
       for (int j=0; j<words.length; j++){ 
            if (words[j].isEmpty()) break; 

所以,这就是为什么你看到你所看到的行为的猜测...在访问它们之前总是初始化变量。

答案 1 :(得分:0)

请告诉我们EconomFactory.eINSTANCE.createItemGroup()中会发生什么?我无法判断每次都是否创建了具有唯一项目列表的唯一实例。

我尝试了一些修改(我目前没有使用Java 6,所以不能使用String.isEmpty)并假设常规对象创建,它适用于我。请参阅下面我的可运行示例(下次您提出问题时应该发布的内容):

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class ItemGrouper {

    public static class Item {
        String id;
        float total;

        Item(String id) {
            this.id = id;
        }

        public String getId() {
            return id;
        }
    }

    public static class ItemGroup {
        String keyword;
        int frequency;
        List<Item> items = new ArrayList<ItemGrouper.Item>();

        public void incrementFrequency() {
            frequency++;
        }

        public List<Item> getItems() {
            return items;
        }

        public void setKeyword(String string) {
            keyword = string;
        }

        @Override
        public String toString() {
            return String.format("key=%s freq=%s", keyword, frequency);
        }
    }

    public static ItemGroup[] createGroups(Item[] items) {

        Map<String, ItemGroup> groups = new HashMap<String, ItemGroup>();
        String[] words;
        for (int i = 0; i < items.length; i++) {
            words = items[i].getId().split(" ");

            // Process keywords
            for (int j = 0; j < words.length; j++) {
                if (words[j].length() == 0) {
                    break;
                }

                ItemGroup group = groups.get(words[j]);
                if (group == null) {
                    group = new ItemGroup();
                    group.setKeyword(words[j]);
                    groups.put(words[j], group);
                }
                group.incrementFrequency();
                group.getItems().add(items[i]);
            }
        }
        return groups.values().toArray(new ItemGroup[0]);
    }

    public static void main(String[] args) {
        Item[] items = new Item[] {new Item("one two"), new Item("two three")};
        ItemGroup[] itemgroups = createGroups(items);
        System.out.println(Arrays.toString(itemgroups));
    }
}

输出:

[key=one freq=1, key=two freq=2, key=three freq=1]