在Map </integer>中设置<integer>

时间:2010-10-05 20:12:54

标签: java

我有一个问题。首先,我宣布了一张地图:

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中。 感谢。

7 个答案:

答案 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);