设置:防止插入相同类型

时间:2018-01-31 10:03:53

标签: java collections set

如果已经存在相同类型的对象,我想阻止在Set中插入对象。 示例:

如果我有以下课程:

public class Card{...}
public class Clubs extends Card{...}
public class Diamonds extends Card{...}
public class Hearts extends Card{...}
public class Spades extends Card{...}

行为应该是:

Set<Card> cards = new HashSet<>();
System.out.println(cards.add(new Diamonds()) //prints "true"
System.out.println(cards.add(new Spades()) //prints "true"
System.out.println(cards.add(new Spades()) //prints "false"

是否有一种简单的方法或一组实现可以给我这种行为?

我考虑过为每个扩展Card的类重写hashcode / equals以管理hashset行为,但我认为这不是一个可靠的解决方案。

编辑:

我举了一张基本卡牌的例子,但每张牌不仅是一种“颜色”,每个类别(俱乐部,钻石,黑桃,红心)的领域数量,领域类型和方法都不同。

EDIT2

这是我班级卡片的更具体的定义:

public abstract class Card
{
    /**Keyword of this card*/
    private final String keyword;

    public Card(String keyword)
    {
         this.keyword = keyword; 
    }

    public abstract void cardDefinition();
    ...
}

这里我的类扩展卡的定义:

public class Diamonds extends Card
{
    /**KEYWORD of this card*/
    public static final String KEYWORD = "cell";
    /**Name of this cell*/
    private final int id;
    /**Universe of this cell*/
    private final Universe universe;
    /**Material name of this cell*/
    private final String materialName;

    public Diamonds(int id, Universe universe, String materialName)
    {
        super(KEYWORD);
        this.id = id;
        this.universe = universe;
        this.materialName = materialName;
        ...
    }
    @Override
    public void cardDefinition(){...}
    public void someMethod(OrientedSurface orientedSurface) {...}
    ...
}


public class Spades extends Card
{
    /**keyword of this card*/
    public static final String KEYWORD = "mat";
    /**Name of this material card*/
    private final String name;
    /**Density of this material card*/
    private final double density;'

    public Spades(String name, double density)
    {
        super(KEYWORD);
        this.name = name;
        this.density = density;
        ...
    }
    @Override
    public void cardDefinition(){...}
    public void someMethodBis(Material material) {...}
    ...
}
...

3 个答案:

答案 0 :(得分:1)

HashSet实现分别使用您插入的对象的equals() hashCode()方法。

换句话说:如果您想让任何Spade 等于与任何其他Spade对象相同 - 您必须@Override equals()并且hashCode()因此。{/ p>

当然 - 这首先是一个相当错误的设计。

西装不应该是,而是enums。然后使用 EnumSet

换句话说,你宁愿选择:

public enum Suit { DIAMONDS, SPADE, ...

public enum Value { TWO, THREE, ... JOKER ... whatever

然后

public class Card {
  private final Suit suit;
  private finale Value value;

含义:您使用枚举来创建枚举此类值的类型。然后你的卡片对象只需分配套装,价值,......等等。通过使用enum和EnumSet,你基本上可以获得你想要的东西......免费。

最后:好的OOP不仅仅是将extends放在这里或那里。您的课程模型现实。西装一张卡片!该套装是卡的属性

答案 1 :(得分:1)

根据您更新的答案,使用关键字到Card的映射可能对您有用:

Map<String, Card> cards = new HashMap<>();

这假设关键字是唯一的,并且每个关键字只有一张卡应该在地图中。在地图中存储数据可能如下所示:

Card mySpade = new Spade(...);

if (!cards.contains(Spades.KEYWORD)) {
    cards.put(Spades.KEYWORD, mySpade);
}...

答案 2 :(得分:0)

为作业编写一个专用类,它在内部使用一个集合。此类提供public方法来添加新卡,在将卡真正添加到集合之前,它会检查是否允许。从外部您无权访问包含该集合的private字段,因此您必须使用强制执行检查的方法。