我有3个班级:A,B和C.
A类包含2个B类对象.C类(“容器”)有一个A对象列表,因为有时我需要直接迭代所有创建的B对象,所以包含B对象的列表由A对象。
class A {
private B b1;
private B b2;
...
}
class B {...}
class C {
List<A> aList;
List<B> bList;
...
}
这是多余的,显然容易出错。
有没有办法迭代 aList 中A对象包含的所有B对象的集合?
我正在寻找一些语法糖来避免代码如下:
public B hasFoo(Q){
for(A a:aList){
if(a.getB1().hasFoo(Q))return a.getB1();
if(a.getB2().hasFoo(Q))return a.getB2();
}
}
答案 0 :(得分:1)
不幸的是,答案是否定的,没有更简洁的方式来编写你已经拥有的东西。
如果没有额外的冗余数据结构,您将需要遍历所有A对象,然后迭代它们中包含的所有B对象,就像在您的示例中一样。
轻微的设计改进可能是让A对象自己执行B对象的迭代。 E.g。
// In class A
public B getAppropriateB(Q)
{
if (B1.hasFoo(Q)) return B1;
if (B2.hasFoo(Q)) return B2;
return null; // or throw an exception...
}
然后在C班:
public B hasFoo(Q){
for(A a:aList){
B b = a.hasAppropriateB(Q);
if (b != null) return b;
}
}
但是,这并不能保存任何字符,如果这是您正在寻找的特定字符。
如果每个A对象有很多B对象(如示例中所示,只有2个以上),那么使用反射迭代B对象可能(非常试探性和有条件的)可能是值得的。这很可能(几乎肯定)是不明智的,除非直接编写B迭代代码是不可行的。
答案 1 :(得分:1)
如果你想要在b1和b2(不仅仅是hasFoo())上执行许多不同的操作,你可以在A中设置一个迭代器,让你循环b1和b2都有。这样的东西有用,虽然它看起来有点像黑客:
class A {
private B b1;
private B b2;
private class TheBees implements Iterable<B> {
public Iterator<B> iterator() {
return new Iterator<B> () {
private int which = 0;
public boolean hasNext() { return which < 2; }
public B next() {
which++;
if (which == 1) return b1;
if (which == 2) return b2;
throw new NoSuchElementException ();
}
public void remove() { throw new UnsupportedOperationException (); }
};
}
}
public Iterable<B> theBees () {
return (new TheBees ());
}
// other stuff...
}
现在你可以写
了for (A a : aList) {
for (B b : a.theBees())
if (b.hasFoo(Q)) return b;
}
这是一个非常多的垃圾,只是为了让这个循环看起来更好。但是如果这是一个你会使用很多的模式,除了hasFoo()之外的其他东西,它可能是值得的。如果你想减少hacky,我会修改A来保存B的两个元素数组(而不是b1和b2),然后TheBees.iterator()可以只返回Arrays.asList(bArray).iterator( )[注意:我没试过]。
答案 2 :(得分:0)
如果'B'需要在它的类之外(逻辑上)访问,那么将其private
用于它是没有用的。所以只需要制作B public
,但要确保提供标准的getter和setter,而不是直接对字段进行处理。