在Java中,如何检查集合是否包含特定类的实例?

时间:2011-10-12 02:59:15

标签: java generics

例如(这是非常简化的),假设我在一副牌中的每张牌都有一个等级......例如一个KingOfSpaces类,一个QueenOfSpades类,一个JackOfDiamonds类等等。所有这些都延伸Card。可能存在KingOfSpaces的多个实例。

我有一个ArrayList<Card>,其中有5个对象。如何查看ArrayList是否包含至少一个AceOfDiamonds

8 个答案:

答案 0 :(得分:12)

让我们首先指出,使用类进行这种区分几乎肯定是一件坏事。我要说你可能需要让'Card'更聪明一些(即使用getSuit()和getOrdinal()方法)。

但是,如果你坚持这样做,迭代数组列表(你可以google - 这是一个非常基本的东西)并使用instanceof运算符比较列表中的每个条目。

您将此问题标记为与“反射”有关,这似乎不正确。你确定你不打算将它标记为“作业”吗?

好的 - 到底是什么,这是代码:

List<Card> hand = ...;
for(Card card : hand){
  if (card instanceof AceOfDiamonds) return true;
}

但请不要设置你的类层次结构 - 这是一个可怕的设计。

答案 1 :(得分:4)

尝试使用instanceof运算符:

if (myObject instanceof myType) {
    System.out.println("myObject is an instance of myType!");
}

答案 2 :(得分:4)

@Daniel Pereira回答了问题。我想提出你真正想要的是enum

示例:

enum Card {
    KingOfSpades,
    QueenOfSpades,
    JackOfSpades,
    // etc
    AceOfDiamonds;
}

Card myCard = ...;
if(myCard == Card.KingOfSpades) {
    // stuff
}

Set<Card> cards = new EnumSet<Card>(Card.class);
cards.add(...);
if(cards.contains(myCard)) {
   // stuff
}

答案 3 :(得分:2)

现在,您可以以一种非常简单的单线方式对流执行此操作:

List<Card> myList = fillitSomehow();
myList.stream().anyMatch(c -> c instanceof AceOfDiamonds);

答案 4 :(得分:1)

您可以使用以下代码:

private boolean findInstance(ArrayList items, String className) {
    boolean tag = false;
    for (int i = 0; i < items.size(); i++) {
        if (items.get(i).getClass().getName().equals(className)) {
            tag = true;
            break;
        }
    }
    return tag;
}

'className'包括包名,例如:'java.lang.String'

答案 5 :(得分:1)

您可以像这样扩展List:

public class XList<T> extends ArrayList {

    public boolean hasInstanceOf(Object obj) {
        for (Class<?extends Object> item: (Collection<Class<? extends Object>>)this ) {
            if (item.isInstance(obj)) return true;
        }
        return false;
    }

}

此解决方案允许您动态检查类型,而不仅仅是静态类型。

您可以像这样实现列表:

xList<Class> classTypes = new xList<Class>();
if (classTypes.hasInstanceOf(item.getClass())){
    return true;
}

答案 6 :(得分:0)

检查对象的类型实质上违反了各种面向对象的原则。您可能想要回答的问题是,一旦找到该类型的对象,您打算做什么。

要执行的动作是必须为每种类型建模的动词。例如,在单人纸牌游戏中,当你点击一张牌时,你可以把它放在右侧的筹码上。因此,卡是否可以落在堆栈上的能力取决于对象本身,因为它知道它的身份。所以基本上你必须为每张卡实现一个deal()方法,并根据它的对象,它知道如何为它的实例实现deal()。通过在对象外部进行(并检查类型),您实际上已经破坏了封装。

答案 7 :(得分:0)

public static <E> boolean containsInstance(List<E> list, Class<? extends E> clazz) {
    for (E e : list) {

        try {
            List<E> list2 = (List<E>) e;
            for (E list21 : list2) {
                System.out.println("<< ENCONTRO LISTA DENTRO DEL ARRAY DE OBJETOS >> ");
                if (clazz.isInstance(list21)) {
                    return true;
                }
            }
        } catch (Exception q) {
            System.out.println("<< ENCONTRO OBJETO DENTRO DEL ARRAY DE OBJETOS >> ");
            if (clazz.isInstance(e)) {
                return true;
            }
            continue;
        }

    }
    return false;
}