【问题标题】:Is it possible to Iterate on objects contained in another class?是否可以迭代另一个类中包含的对象?
【发布时间】:2013-07-03 20:39:51
【问题描述】:

我有 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();
   }
}

【问题讨论】:

  • 为什么不能通过遍历List&lt;A&gt; 来访问B 属性?这真的不会花费你太多额外的工作。
  • 让问题更清楚,我正在寻找更漂亮的方法!
  • 如果您想从外部访问它们,请不要将它们设为私有。私有意味着它只能从类内部访问。

标签: java list iterator


【解决方案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() 之外还有其他的东西,它可能是值得的。如果你想让它不那么老套,我会修改 A 以保存 B 的二元素数组(而不是 b1 和 b2),然后 TheBees.iterator() 可以只返回 Arrays.asList(bArray).iterator( ) [注意:我没试过]。

【讨论】:

    【解决方案2】:

    很遗憾,答案是否定的,没有更简洁的方法可以写出你已有的内容。

    如果没有额外的冗余数据结构,您将需要遍历所有 A 对象,然后是其中包含的所有 B 对象,就像在您的示例中一样。

    一个轻微的设计改进可能是让 A 对象自己执行其 B 对象的迭代。例如

    // 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 迭代代码是不可行的。

    【讨论】:

      【解决方案3】:

      如果需要在其类之外(逻辑上)访问“B”,则将其设为private 是没有用的。因此,只需设置 B public,但请确保提供标准的 getter 和 setter,而不是直接寻址字段。

      【讨论】:

      • 我更多的是在寻找一些语法糖,我知道如何访问它:) - 我正在编辑问题以使其更清楚!
      猜你喜欢
      • 1970-01-01
      • 2010-09-17
      • 1970-01-01
      • 1970-01-01
      • 2013-05-19
      • 2013-06-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多