创建一个集合作为密钥的地图?

时间:2013-06-19 21:38:45

标签: java collections map comparable

是否可以创建一个密钥是Collection(任何类型的集合)的地图?

如果我在大多数常见的收藏中尝试,我会被告知收藏品不能用于比较。

我一直在尝试为自定义集合编写compareTo函数,但我很挣扎。

要么我需要编写compareTo,要么我需要找到一个接受地图接受的集合/集合的预制地图。

如何将集合用作地图上的键?我已经查看了Stack溢出,我已经多次搜索过这个问题,但我从来没有找到一个可靠的解决方案!


我想这样做的原因是我在Java中编写了一个模拟卡片洗牌的“随机”模拟。我希望能够计算特定手(建模为集合)出现的次数。它看起来像这样:

   H4,C3,D2: 8  
   H9,D6,S11: 10  
   ......

2 个答案:

答案 0 :(得分:10)

  

是否可以创建一个密钥是Collection(任何类型的集合)的地图?

是的,这是可能的,但绝对不推荐。如果您的集合发生更改,则其哈希码可能也会发生变化,这可能会导致令人惊讶的行为。

请参阅Map's javadoc

  

注意:如果将可变对象用作映射键,则必须非常小心。如果在对象是地图中的键时,以影响等于比较的方式更改对象的值,则不指定映射的行为。


  

如果我在大多数常见的收藏中尝试,我会被告知收藏品不能用于比较。

除非您使用有序地图,即TreeMap,否则密钥不需要具有可比性。使用简单的HashMap,你就不会有问题。


在编辑之后,我将创建一个新的不可变Hand类:

class Hand implements Comparable<Hand> {
    private final List<Card> cards;
    Hand(Card c1, Card c2, Card c3) {
        cards = Collections.unmodifiableList(Arrays.asList(c1, c2, c3));
    }
    //getters, no setters
    //implement compareTo
}

并实施compareTo,如果您想在TreeSet<Hand, Integer>中使用它并按手工强度排序,例如。

答案 1 :(得分:2)

是的,您可以将任何集合用作关键字。如果你想要像TreeMap这样的SortedMap,你必须提供一个Comparator来确定顺序。但是,如果您使用任何类型的HashMap,则不需要。

Map<List<Integer>, String> map = new HashMap<>();
map.put(Arrays.asList(1,2,3), "one to three");
map.put(Arrays.asList(7,8,9), "seven eat nine");
System.out.println(map);

打印

{[1, 2, 3]=one to three, [7, 8, 9]=seven eat nine}