有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

有人能解释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]);                       
}

奇怪的是,将项目添加到项目组(line group.getItems())时。添加(项[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]);                       
}

这种方法在工厂里是可行的。爱因斯坦。createItemGroup()的实现如下:

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

其中ItemGroupImpl是ItemGroup的实现,即它是ItemGroup的子类。这是因为我使用EMF(Eclipse建模框架)

谁能解释一下这种行为(为什么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) 个答案

  1. # 1 楼答案

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

     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”,并且你用这个值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; 
    

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

  2. # 2 楼答案

    请告诉我们工厂里发生了什么。爱因斯坦。createItemGroup()?我无法判断是否每次都创建了具有唯一项列表的唯一实例

    我做了一些修改(我目前没有使用Java6,所以不能使用String.isEmpty),并假设定期创建对象,这对我来说是可行的。请参见下面我的runnable示例(类似于下次提问时应该发布的内容):

    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]