Java 在 Map 中设置 <Integer>

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3867333/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 06:04:00  来源:igfitidea点击:

Set<Integer> inside Map

java

提问by user433947

I have a question. First, I declared a map:

我有个问题。首先,我声明了一张地图:

Map<TwoIntClass, Set<Integer>> m = new HashMap<TwoIntClass, Set<Integer>>();

Now, I want to put stuff inside this map, something like

现在,我想把东西放在这张地图里,比如

int num = 7;
m.put(new TwoIntClass(5, 3), ?? how to put num inside Set ??);

My question is, how do I put variable num inside Set. Thanks.

我的问题是,如何将变量 num 放入 Set 中。谢谢。

采纳答案by Yanick Rochon

Like Hymanand others have suggested, you need to instantiate a concrete instance of the Setinterface (like HashSet), add your intvalues in the Setand then put the Setinto your Map. However, if you are using a custom class for your Map's key, I would suggest you implement the equals()and hashCode()method of your TwoIntClassclass to be sure that you are not creating duplicate entries inside your Map. For example, consider this class :

就像Hyman和其他人所建议的那样,您需要实例化Set接口的具体实例(如HashSet),将您的int值添加到 中Set,然后将Set放入您的Map. 但是,如果您为您Map的密钥使用自定义类,我建议您实现类的equals()andhashCode()方法,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) );

    }
}

The output for executing it is :

执行它的输出是:

1476323068 = 535746438 == false > map count = 2

Looking for TwoIntClass(5,3)... false

1476323068 = 535746438 == false > 地图计数 = 2

寻找 TwoIntClass(5,3)... false

As you see, they both are "equal" (i.e. they both are constructed with the same integers), but they are distinct objects with different hash codes, therefore create two entries in the map. This could lead into possible data corruption in your application. Moreover, executing this line : map.get(new TwoIntClass(5,3)).add(3);will generate a NullPointerExceptionbecause the key (it's hash) does not exist in the map. So, you need to implement the equals()and hashCode()methods to fix this, so any TwoIntClassconstructed with the same integers will be considered equal. Something like :

如您所见,它们都是“相等的”(即它们都是用相同的整数构造的),但它们是具有不同哈希码的不同对象,因此在映射中创建了两个条目。这可能会导致您的应用程序中的数据损坏。此外,执行这一行 :map.get(new TwoIntClass(5,3)).add(3);将生成 aNullPointerException因为映射中不存在键(它的哈希)。因此,您需要实现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;
}

yields a more expected result of

产生更预期的结果

1476323071 = 1476323071 == true > map count = 1

Looking for TwoIntClass(5,3)... true

1476323071 = 1476323071 == 真 > 地图计数 = 1

寻找 TwoIntClass(5,3)... true

Of course, this hashCode()method is oversimplistic and you may need to find a yet better construct, but the bottom line is that implementing them is what I would recommend.

当然,这个hashCode()方法是超过简单化,您可能需要找到更好的构造,但最重要的是,我会推荐实施它们。

回答by jjnguy

You will have to create the set first, add the item, and then put the set in the map. There is no good way to initialize a set inline in Java. (This may change when java 7 comes out.)

您必须先创建集合,添加项目,然后将集合放入地图中。在 Java 中没有好的方法来初始化一个内联的集合。(当 java 7 出现时,这可能会改变。)

int num = 7;
Set<Integer> set = new HashSet<Integer>();
set.add(num);
m.put(new TwoIntClass(5, 3), set);

回答by nanda

Set set = new HashSet();
set.add(2);
set.add(4);
...
m.put(new TwoIntClass(5, 3), set);

Slightly better (from here):

稍微好一点(从这里开始):

m.put(new TwoIntClass(5, 3), new HashSet(Arrays.asList(1, 2)));

You can modify the set like this:

您可以像这样修改集合:

m.get(new TwoIntClass(5, 3)).add(6);

回答by Hyman

You have to be sure that the related Setis instantiated and inserted into the Mapbefore doing anything. You could use something like

在做任何事情之前,您必须确保相关项Set已实例化并插入到 中Map。你可以使用类似的东西

public void safeInsert(TwoIntClass tic, Integer element)
{
  if (!map.contains(tic))
    map.put(tic, new HashSet<Integer>());

  map.get(tic).add(element);
}

Mind that you can't use directly Setsince it's an interface, so choose an actual implementation (eg. HashSet)

请注意您不能直接使用,Set因为它是一个接口,所以选择一个实际的实现(例如。HashSet

With Java8 every thing become easier:

有了 Java8,一切都变得更容易了:

map.computeIfAbsent(tic, k -> new HashSet<>()).add(element);

回答by Péter T?r?k

int num = 7;
TwoIntClass twoInts = new TwoIntClass(5, 3);
m.put(twoInts, new HashSet<Integer>());
m.get(twoInts).add(num);

回答by Michael D

Each time you want to put something in the set, you need to check if the set already exists, and create the set if it does not. ie:

每次要在集合中放入一些东西时,都需要检查该集合是否已经存在,如果不存在则创建该集合。IE:


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

There's a perfect abstraction over this in google's guava libraries called SetMultimapthat you should consider using, especially if this is a repeated pattern in your code.

谷歌的番石榴库中有一个完美的抽象,称为SetMultimap,您应该考虑使用它,特别是如果这是您的代码中的重复模式。

回答by ColinD

I'd recommend using a SetMultimapfrom Guavainstead. This saves you from having to think about creating the sets yourself.

我建议使用SetMultimap番石榴代替。这使您不必考虑自己创建集合。

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