是否可以添加ArrayList
作为HashMap
的关键字。我想保留双字母的频率数。二元组是关键,价值就是它的频率。
对于像“他是”这样的每个双子星,我为它创建一个ArrayList
并将其插入HashMap
。但我没有得到正确的输出。
public HashMap<ArrayList<String>, Integer> getBigramMap(String word1, String word2) {
HashMap<ArrayList<String>, Integer> hm = new HashMap<ArrayList<String>, Integer>();
ArrayList<String> arrList1 = new ArrayList<String>();
arrList1 = getBigram(word1, word2);
if (hm.get(arrList1) != null) {
hm.put(arrList1, hm.get(arrList1) + 1);
} else {
hm.put(arrList1, 1);
}
System.out.println(hm.get(arrList1));
return hm;
}
public ArrayList<String> getBigram(String word1, String word2) {
ArrayList<String> arrList2 = new ArrayList<String>();
arrList2.add(word1);
arrList2.add(word2);
return arrList2;
}
答案 0 :(得分:26)
是的,您可以将ArrayList
作为哈希映射中的键,但它是非常糟糕的主意,因为它们可变。
如果以任何方式(或其任何元素)更改ArrayList
,映射将基本上丢失,因为密钥将不具有与其时相同的hashCode
插入
经验法则是仅使用不可变数据类型作为哈希映射中的键。正如Alex Stybaev所建议的那样,您可能想要创建一个Bigram
类,如下所示:
final class Bigram {
private final String word1, word2;
public Bigram(String word1, String word2) {
this.word1 = word1;
this.word2 = word2;
}
public String getWord1() {
return word1;
}
public String getWord2() {
return word2;
}
@Override
public int hashCode() {
return word1.hashCode() ^ word2.hashCode();
}
@Override
public boolean equals(Object obj) {
return (obj instanceof Bigram) && ((Bigram) obj).word1.equals(word1)
&& ((Bigram) obj).word2.equals(word2);
}
}
答案 1 :(得分:2)
为什么你不能使用这样的东西:
class Bigram{
private String firstItem;
private String secondItem;
<getters/setters>
@Override
public int hashCode(){
...
}
@Override
public boolean equals(){
...
}
}
而不是将动态集合用于有限数量的项目(两个)。
答案 2 :(得分:2)
注意:如果将可变对象用作地图,则必须非常小心 键。如果对象的值是,则不指定映射的行为 以一种影响
equals
比较的方式改变了 对象是地图中的关键。这个禁令的一个特例就是它 不允许地图将自己包含为关键字。虽然它是 允许地图将自己包含为一个值,极其谨慎 建议:不再使用equals
和hashCode
方法 在这样的地图上明确定义。
为了hashCode
和equals
而使用可变对象作为键,您必须小心。
最重要的是,最好将不可变对象用作键。
答案 3 :(得分:1)
试试这个,这样可行。
public Map<List, Integer> getBigramMap (String word1,String word2){
Map<List,Integer> hm = new HashMap<List, Integer>();
List<String> arrList1 = new ArrayList<String>();
arrList1 = getBigram(word1, word2);
if(hm.get(arrList1) !=null){
hm.put(arrList1, hm.get(arrList1)+1);
}
else {
hm.put(arrList1, 1);
}
System.out.println(hm.get(arrList1));
return hm;
}
答案 4 :(得分:1)
我已经提出了这个解决方案。它显然在所有情况下都不可用,例如在步进哈希码int容量或list.clone()并发症时(如果输入列表被更改,键保持与预期相同,但当List的项是可变的时,克隆list对其项目具有相同的引用,这将导致更改密钥本身。)
import java.util.ArrayList;
public class ListKey<T> {
private ArrayList<T> list;
public ListKey(ArrayList<T> list) {
this.list = (ArrayList<T>) list.clone();
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
for (int i = 0; i < this.list.size(); i++) {
T item = this.list.get(i);
result = prime * result + ((item == null) ? 0 : item.hashCode());
}
return result;
}
@Override
public boolean equals(Object obj) {
return this.list.equals(obj);
}
}
---------
public static void main(String[] args) {
ArrayList<Float> createFloatList = createFloatList();
ArrayList<Float> createFloatList2 = createFloatList();
Hashtable<ListKey<Float>, String> table = new Hashtable<>();
table.put(new ListKey(createFloatList2), "IT WORKS!");
System.out.println(table.get(createFloatList2));
createFloatList2.add(1f);
System.out.println(table.get(createFloatList2));
createFloatList2.remove(3);
System.out.println(table.get(createFloatList2));
}
public static ArrayList<Float> createFloatList() {
ArrayList<Float> floatee = new ArrayList<>();
floatee.add(34.234f);
floatee.add(new Float(33));
floatee.add(null);
return floatee;
}
Output:
IT WORKS!
null
IT WORKS!
答案 5 :(得分:0)
当然有可能。我想你put
中的问题。尝试获取bigram的密钥,递增它,使用此bigram删除条目并插入更新的值
答案 6 :(得分:0)
与Array
不同,List
可以用作HashMap的键,但这不是一个好主意,因为我们应该始终尝试使用不可变的对象作为键< / strong>。
.toString()
方法获得String表示形式是一个不错的关键选择,因为String
是一个固定的对象,可以完美地代表数组或列表。
答案 7 :(得分:-1)
请检查下面我的代码,以了解key是否是Map中的ArrayList以及JVM将如何为输入执行此操作: 在这里,我为TesthashCodeEquals类编写hashCode和equals方法。
package com.msq;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
class TesthashCodeEquals {
private int a;
private int b;
public TesthashCodeEquals() {
// TODO Auto-generated constructor stub
}
public TesthashCodeEquals(int a, int b) {
super();
this.a = a;
this.b = b;
}
public int getA() {
return a;
}
public void setA(int a) {
this.a = a;
}
public int getB() {
return b;
}
public void setB(int b) {
this.b = b;
}
public int hashCode() {
return this.a + this.b;
}
public boolean equals(Object o) {
if (o instanceof TesthashCodeEquals && o != null) {
TesthashCodeEquals c = (TesthashCodeEquals) o;
return ((this.a == c.a) && (this.b == c.b));
} else
return false;
}
}
public class HasCodeEquals {
public static void main(String[] args) {
Map<List<TesthashCodeEquals>, String> m = new HashMap<>();
List<TesthashCodeEquals> list1=new ArrayList<>();
list1.add(new TesthashCodeEquals(1, 2));
list1.add(new TesthashCodeEquals(3, 4));
List<TesthashCodeEquals> list2=new ArrayList<>();
list2.add(new TesthashCodeEquals(10, 20));
list2.add(new TesthashCodeEquals(30, 40));
List<TesthashCodeEquals> list3=new ArrayList<>();
list3.add(new TesthashCodeEquals(1, 2));
list3.add(new TesthashCodeEquals(3, 4));
m.put(list1, "List1");
m.put(list2, "List2");
m.put(list3, "List3");
for(Map.Entry<List<TesthashCodeEquals>,String> entry:m.entrySet()){
for(TesthashCodeEquals t:entry.getKey()){
System.out.print("value of a: "+t.getA()+", value of b: "+t.getB()+", map value is:"+entry.getValue() );
System.out.println();
}
System.out.println("######################");
}
}
}
output:
value of a: 10, value of b: 20, map value is:List2
value of a: 30, value of b: 40, map value is:List2
######################
value of a: 1, value of b: 2, map value is:List3
value of a: 3, value of b: 4, map value is:List3
######################
所以这将检查List中的对象数和对象中的valriabe值。如果对象的数量相同且实例变量的值也相同,那么它将考虑重复键并覆盖该键。
现在,如果我只改变list3上对象的值
list3.add(new TesthashCodeEquals(2,2));
然后会打印出来:
output
value of a: 2, value of b: 2, map value is:List3
value of a: 3, value of b: 4, map value is:List3
######################
value of a: 10, value of b: 20, map value is:List2
value of a: 30, value of b: 40, map value is:List2
######################
value of a: 1, value of b: 2, map value is:List1
value of a: 3, value of b: 4, map value is:List1
######################
这样它总是检查List中的对象数和object的实例变量的值。
感谢
答案 8 :(得分:-3)
ArrayList.equals()
继承自java.lang.Object
- 因此,ArrayList上的equals()
独立于列表的内容。
如果要将ArrayList用作地图键,则需要覆盖equals()
和hashcode()
,以使两个具有相同内容的相同内容的arraylists在通话时返回true到equals()
并在调用hashcode()
时返回相同的哈希码。
是否有任何特殊原因使 使用ArrayList而不是简单的String作为键?
编辑:忽略我,正如Joachim Sauer在下面指出的那样,我错了,甚至都不好笑。