ArrayList <string>的HashMap,String无法正常工作?</string>

时间:2013-02-12 05:20:31

标签: java string arraylist hashmap

所以,我想制作一个字符串列表到字符串的地图,但我不能让它正常工作:

这是我所做的所有代码,直到我找到原因,我无法进步:

Map<List<String>, String> test = new HashMap<List<String>, String>();
test.put( new ArrayList<String>(), "s1");
test.put( new ArrayList<String>(), "s2");
test.put( new ArrayList<String>(), "s3");

System.out.println(test.size());

我得到1,应该是3 !! 为什么在我为3个独立的对象进行3次调用时只添加了一个对象?我知道不小心将同一个对象添加到集合中的危险,但我专门为每个put创建了一个新的ArrayList,从而创建了一个全新的对象。

那么为什么Map中只有一个对象呢? 谢谢!

5 个答案:

答案 0 :(得分:3)

试试这个:

Map<String,List<String>> test = new HashMap<String,List<String>>();
test.put("s1", new ArrayList<String>());
test.put("s2", new ArrayList<String>());
test.put("s3", new ArrayList<String>());

System.out.println(test.size());

请注意,地图是key-value关系。因此,您可能希望将String用作,将ArrayList用作,而不是相反。这样,如果添加3个不同的字符串,每个字符串将具有不同的哈希值(哈希码)。因此,Map中有3个不同的密钥。

另请注意:

<强>把

  

public Object put(对象键,                     Object value)将指定的值与此映射中的指定键相关联。如果之前的地图包含a   此键的映射,旧值已替换

这就是为什么你得到1而不是3,因为你要添加相同的对象new ArrayList<String>()

详细了解Class HashM规范。

答案 1 :(得分:2)

ArrayList #hashCode()为所有这些返回相同的内容。如果你看一下它的来源:http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/AbstractList.java#AbstractList.hashCode%28%29

你可以看到,如果没有元素或所有相同的元素,hashCode将是相同的。

解决这个问题,它应该可以正常工作。使用Map或以某种方式更改hashCode。

答案 2 :(得分:1)

使用ArrayList作为键,尝试

    System.out.println(new ArrayList<String>().equals(new ArrayList<String>()));

打印

true

答案 3 :(得分:0)

最好的方法是使用String对象作为键,将List作为值。

查看java文档所说的here

如果你想将ArrayList作为键添加,那么覆盖equals方法就足够了。

帖子here提供了很好的见解。我把那些我喜欢的东西放在那篇文章中。

覆盖两个ArrayLists的等于:

 public boolean equals(List<String> one, List<String> two){
    if (one == null && two == null){
        return true;
    }

    if((one == null && two != null) 
      || one != null && two == null
      || one.size() != two.size()){
        return false;
    }

    //to avoid messing the order of the lists we will use a copy
    //as noted in comments by A. R. S.
    one = new ArrayList<String>(one); 
    two = new ArrayList<String>(two);   

    Collections.sort(one);
    Collections.sort(two);      
    return one.equals(two);
}

答案 4 :(得分:0)

我不确定为什么你需要列表作为键,字符串作为值,但是你基本上对每个put操作使用相同的'key',因为hashcode对于任何空列表都是相同的。与其他答案一样,最好将列表作为值切换,将字符串作为键。如果列表发生更改,则以后对.get的任何尝试都将返回null

   public static void main(String...args) {
       Map<List<String>, String> test = new HashMap<List<String>, String>();
       List<String> bob = new ArrayList<>();
       bob.add("asdf");
       test.put( new ArrayList<String>(), "s1");
       test.put( bob, "s2");

       System.out.println(test.size());
       System.out.println(test.get(bob));
   }

输出

2
s2

添加新项目时

   public static void main(String...args) {
       Map<List<String>, String> test = new HashMap<List<String>, String>();
       List<String> bob = new ArrayList<>();
       bob.add("asdf");
       test.put( new ArrayList<String>(), "s1");
       test.put( bob, "s2");      
       bob.add("aabbcc");

       System.out.println(test.size());
       System.out.println(test.get(bob));
   }

get不起作用,因为列表的哈希值已经改变。这种情况下的输出是:

2
null