如果已经存在相同类型的对象,我想阻止在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行为,但我认为这不是一个可靠的解决方案。
我举了一张基本卡牌的例子,但每张牌不仅是一种“颜色”,每个类别(俱乐部,钻石,黑桃,红心)的领域数量,领域类型和方法都不同。
这是我班级卡片的更具体的定义:
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) {...}
...
}
...
答案 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
字段,因此您必须使用强制执行检查的方法。