我有一个问题。首先,我宣布了一张地图:
Map<TwoIntClass, Set<Integer>> m = new HashMap<TwoIntClass, Set<Integer>>();
现在,我想将内容放入此地图中,例如
int num = 7;
m.put(new TwoIntClass(5, 3), ?? how to put num inside Set ??);
我的问题是,如何将变量num放入Set中。 感谢。
答案 0 :(得分:7)
与Jack和其他人建议的一样,您需要实例化Set
界面的具体实例(例如HashSet
),在{{int
中添加Set
值1}}然后将Set
放入Map
。但是,如果您使用Map
密钥的自定义类,我建议您实施equals()
类的hashCode()
和TwoIntClass
方法,以确保您没有在Map
内创建重复的条目。例如,考虑这个类:
public class TwoIntClass {
private int i1;
private int i2;
public TwoIntClass(int i1, int i2) {
this.i1 = i1;
this.i2 = i2;
}
static public void main(String...args) {
Map<TwoIntClass, Set<Integer>> map = new HashMap<TwoIntClass, Set<Integer>>();
Set<Integer> dataset = new HashSet<Integer>();
dataset.add(1);
dataset.add(2);
TwoIntClass i1 = new TwoIntClass(5, 3);
TwoIntClass i2 = new TwoIntClass(5, 3);
map.put(i1, dataset);
map.put(i2, dataset);
System.out.println( i1.hashCode() + " = " + i2.hashCode() + " == " + i2.equals(i2) + " > map count = " + map.size() );
TwoIntClass i3 = new TwoIntClass(5, 3);
System.out.println("Looking for TwoIntClass(5,3)... " + map.containsKey(i3) );
}
}
执行它的输出是:
1476323068 = 535746438 == false&gt;地图 count = 2
寻找TwoIntClass(5,3)... false
如您所见,它们都是“相等的”(即它们都是用相同的整数构造的),但它们是具有不同哈希码的不同对象,因此在地图中创建两个条目。这可能会导致应用程序中的数据损坏。此外,执行此行:map.get(new TwoIntClass(5,3)).add(3);
将生成NullPointerException
,因为地图中不存在密钥(它的哈希)。因此,您需要实现equals()
和hashCode()
方法来解决此问题,因此使用相同整数构造的任何TwoIntClass
都将被视为相等。类似的东西:
@Override
public boolean equals(Object obj) {
if (!(obj instanceof TwoIntClass)) {
return false;
}
TwoIntClass other = (TwoIntClass) obj;
return (other.i1 == this.i1) && (other.i2 == this.i2);
}
@Override
public int hashCode() {
//return TwoIntClass.class.hashCode() | i1 | (i2 << 16);
// better implementation based on the String class
int hash = TwoIntClass.class.hashCode();
hash = (hash * 31) + i1;
hash = (hash * 31) + i2;
return hash;
}
产生更期望的
结果1476323071 = 1476323071 == true&gt; map count = 1
寻找TwoIntClass(5,3)...... true
当然,这个hashCode()
方法是 over 简单化,你可能需要找到一个better construct,但最重要的是实现它们是我推荐的
答案 1 :(得分:4)
Set set = new HashSet();
set.add(2);
set.add(4);
...
m.put(new TwoIntClass(5, 3), set);
略好(来自here):
m.put(new TwoIntClass(5, 3), new HashSet(Arrays.asList(1, 2)));
您可以像这样修改设置:
m.get(new TwoIntClass(5, 3)).add(6);
答案 2 :(得分:4)
在执行任何操作之前,您必须确保相关的Set
已实例化并插入Map
。你可以使用像
public void safeInsert(TwoIntClass tic, Integer element)
{
if (!map.contains(tic))
map.put(tic, new HashSet<Integer>());
map.get(tic).add(element);
}
请注意,您不能直接使用Set
因为它是一个接口,所以选择一个实际的实现(例如。HashSet
)
使用Java8,每件事都变得更容易:
map.computeIfAbsent(tic, k -> new HashSet<>()).add(element);
答案 3 :(得分:4)
我建议您使用SetMultimap中的Guava。这样您就不必考虑自己创建集合。
SetMultimap<TwoIntClass, Integer> multimap = HashMultimap.create();
TwoIntClass twoInts = new TwoIntClass(5, 3);
int num = 7;
multimap.put(twoInts, num);
Set<Integer> set = multimap.get(twoInts); // set contains 7
multimap.put(twoInts, 8);
multimap.put(twoInts, 9); // set now contains 7, 8 and 9
答案 4 :(得分:1)
您必须先创建设置,添加项目,然后将设置放在地图中。在Java中初始化内联集没有好办法。 (当java 7出来时,这可能会改变。)
int num = 7;
Set<Integer> set = new HashSet<Integer>();
set.add(num);
m.put(new TwoIntClass(5, 3), set);
答案 5 :(得分:1)
每次要在集合中放置某些内容时,您需要检查该集合是否已存在,如果不存在则创建集合。即:
int num = 7;
TwoIntClass twoInt = new TwoIntClass(5, 3);
Set<Integer> intSet = m.get(twoInt);
if(num == null) {
intSet = new HashSet<Integer>();
intSet.put(twoInt, intSet);
}
intSet.add(num);
在谷歌的guava库{@ 3}}中有一个完美的抽象,你应该考虑使用它,特别是如果这是你代码中的重复模式。
答案 6 :(得分:0)
int num = 7;
TwoIntClass twoInts = new TwoIntClass(5, 3);
m.put(twoInts, new HashSet<Integer>());
m.get(twoInts).add(num);