Java ArrayList中不同类型(相同接口)的计数

Java ArrayList中不同类型(相同接口)的计数,java,interface,arraylist,Java,Interface,Arraylist,我有两个类实现了相同的接口,如下所示 // Interface Interface ISomething { ... } // Class A class A implements ISomething { ... } // Class B class B implements ISomething { ... } // Interfaces Interface ISomething { public void accept(ISomethingVisitor visitor); } In

我有两个类实现了相同的接口,如下所示

// Interface
Interface ISomething { ... }

// Class A
class A implements ISomething { ... }

// Class B
class B implements ISomething { ... }
// Interfaces
Interface ISomething { public void accept(ISomethingVisitor visitor); }
Interface ISomethingVisitor {
    public void visit(A a);
    public void visit(B b);
}

// Classes
class A implements ISomething {
     @Override
     public void accept(ISomethingVisitor visitor) { visitor.visit(this); }
}
class B implements ISomething {
     @Override
     public void accept(ISomethingVisitor visitor) { visitor.visit(this); }
}
class SomethingCountVisitor implements ISomethingVisitor {
     private int aCount;
     private int bCount;

     @Override
     public void visit(A a) { aCount++; }
     @Override
     public void visit(B b) { bCount++; }
     //getters for aCount, bCount
}

// Example usage
// Assuming items have many A and B instances.
ArrayList<ISomething> items = new ArrayList<ISomething>();
...
SomethingCountVisitor scVisitor = new SomethingCountVisitor();
for (ISomething item in items)
    item.accept(scVisitor);
然后在
ArrayList
中,我有很多A类和B类的实例

是否有一种方法可以在不使用
instanceof
的情况下分别计算a类和B类的出现次数。我用了很多方法(比如在类A和类B中创建新方法,让它们决定是否应该增加传递给它们的整数数组中保留的计数变量),但它们似乎不是好的设计

对不起,我的英语很差,而且在Java和OO设计方面缺乏技巧。如果这是一个糟糕的问题,请让我知道

更新
我试过了,效果很好(比我以前使用的方法更易于维护)。
代码是这样的

// Interface
Interface ISomething { ... }

// Class A
class A implements ISomething { ... }

// Class B
class B implements ISomething { ... }
// Interfaces
Interface ISomething { public void accept(ISomethingVisitor visitor); }
Interface ISomethingVisitor {
    public void visit(A a);
    public void visit(B b);
}

// Classes
class A implements ISomething {
     @Override
     public void accept(ISomethingVisitor visitor) { visitor.visit(this); }
}
class B implements ISomething {
     @Override
     public void accept(ISomethingVisitor visitor) { visitor.visit(this); }
}
class SomethingCountVisitor implements ISomethingVisitor {
     private int aCount;
     private int bCount;

     @Override
     public void visit(A a) { aCount++; }
     @Override
     public void visit(B b) { bCount++; }
     //getters for aCount, bCount
}

// Example usage
// Assuming items have many A and B instances.
ArrayList<ISomething> items = new ArrayList<ISomething>();
...
SomethingCountVisitor scVisitor = new SomethingCountVisitor();
for (ISomething item in items)
    item.accept(scVisitor);
//接口
接口ISomething{public void accept(ISomethingVisitor);}
界面等距访问者{
公众访问(A);
公众访问(B);
}
//班级
A级实现了一件事{
@凌驾
公共无效接受(等距访问者){visitor.visit(this);}
}
B类实现了同样的东西{
@凌驾
公共无效接受(等距访问者){visitor.visit(this);}
}
类SomethingCountVisitor实现ISomethingVisitor{
私人帐户;
私人国际帐户;
@凌驾
公开访问(A){aCount++;}
@凌驾
公共无效访问(B){B计数++;}
//A计数的获取者,B计数
}
//示例用法
//假设项目有多个A和B实例。
ArrayList items=新建ArrayList();
...
SomethingCountVisitor scVisitor=新建SomethingCountVisitor();
用于(项目中的等轴测项目)
物品。接受(访客);

如果你不想使用
instanceof
你只能使用
A.class.isInstance(Object)
谷歌的番石榴为你准备了工具

ArrayList myList=。。。
Iterable iterableOfAs=Iterables.filter(myList,A.class);
int numOfAs=Iterables.size(iterableOfAs)

我强烈建议您在项目中使用番石榴。它可以在数量级上提高您的效率。无论是基于jar的项目还是maven管理的项目,将其添加到项目中都非常简单。

如果始终只有两个类,请在接口中声明一个方法:

boolean isAnA();
在类
A
中实现它以返回true,在类
B
中返回false。使用其结果决定递增哪个计数器

如果可能有两个以上的类,则返回枚举


然而,这一切都相当间接。如果您真的关心它是哪个类,那么instanceof是问这个问题的直接、简单的方法。

答案很简单,不是。因为泛型只在编译时存在,而不是在运行时存在。它们是安全措施,增加什么和不增加什么。但是,一旦编译了代码,
ArrayList
ArrayList
之间就没有区别了


如果不使用
instanceof
进行计数,则无法检查有什么

您可以使用分类相等

class Category<T> {
    private Class<T> klazz;

    public Category(Class<T> klazz) {
        this.klazz = klazz;
    }

    @Override
    public boolean equals(Object obj) {
        return obj != null && klazz.equals(obj.getClass());
    }
}

System.out.println("#A : " + Collections.frequency(list, new Category(A.class)));
System.out.println("#B : " + Collections.frequency(list, new Category(B.class)));
类别{
私家级卡拉兹;
公共类(klazz类){
this.klazz=klazz;
}
@凌驾
公共布尔等于(对象obj){
返回obj!=null&&klazz.equals(obj.getClass());
}
}
System.out.println(“#A:+Collections.frequency(list,newcategory(A.class)));
System.out.println(“#B:+Collections.frequency(列表,新类别(B.class)));

(在Java 8中,解决方案将变得更加直接。)

问题:为什么要有一个ISomething列表,同时需要计算每个子类型的Istance数?在我看来,A和B的两个列表会更好。可能不需要关心它是哪一类,但如果这是重要的,instanceof是一种简单、直接的方法。为什么要避免它呢?当添加新元素时,我希望新元素的类型无关紧要,只要它实现了一件事。这是一个糟糕的设计吗?这不是一个糟糕的设计。但是为什么你需要知道具体的类呢?因为我想计算不同的类型。当添加新元素时,我事先不知道它是哪种类型(但它总是实现ISomething),所以我不能只增加单独的计数变量。如果a和B是参数化类,而不是参数化类,那么答案将是真的。在这种情况下,这个问题是完全正确的。如果您的接口需要了解有关其实现者的任何信息,那么这就是糟糕的设计。谢谢您的建议。我试试看。