【问题标题】:Converting Iterator types in Java在 Java 中转换迭代器类型
【发布时间】:2010-10-08 07:52:11
【问题描述】:

我有一个 Iterator<TypeA>,我想将其转换为 Iterator<TypeB>。 TypeA 和 TypeB 不能直接相互转换,但我可以写一个如何转换它们的规则。我怎样才能做到这一点?我应该扩展和覆盖Iterator<TypeA> 的 next、hasNext 和 remove 方法吗?

【问题讨论】:

  • 你是什么意思“它们不能直接相互转换”?你能提供更多关于你正在尝试做什么以及为什么做的背景吗?
  • 我的 TypeB 对象的数量太多了,所以我将它们作为 TypeA 保存在 DB 中,但显然是 TypeA 的 DB 格式。但最后它们都包含一个字符串字段,我想要一个 Iterator ,所以我想从 TypeA 中取出该字符串并用它创建一个 TypeB 并将其添加到迭代器中,即时。这有意义吗?
  • 28:确实有道理,但您所描述的不是铸造。所以你不能“写一个规则如何施放它们”。您可以编写一些代码将TypeA 转换为TypeB,但不会强制转换。
  • 你是对的,谢谢你的提示。

标签: java iterator types generics


【解决方案1】:

你不需要自己写这个。 Guava(以前的 Google-collections)在 Iterators.transform(...) 中介绍过你吗?

你提供你的迭代器和一个将 TypeA 转换为 TypeB 的函数,你就完成了。

Iterator<TypeA> iterA = ....;
Iterator<TypeB> iterB = Iterators.transform(iterA, new Function<TypeA, TypeB>() {
   @Override
   public TypeB apply(TypeA input) {
     TypeB output = ...;// rules to create TypeB from TypeA
     return output;
   }
});

【讨论】:

  • 不错的解决方案。但是如果我们想在 apply() 方法中抛出一个异常呢?目前不允许,但 apply() 签名。
  • 您仍然可以抛出未经检查的异常,这通常是更好的主意。
  • 我实际上需要抛出一个检查异常,所以我最终创建了自己的转换方法。谢谢
【解决方案2】:

写一个adapter。这是 Java 中的an example。 OReilly 的书'Head First: Design Patterns' 对这个主题给出了最好的解释。

【讨论】:

    【解决方案3】:

    我猜你应该用你的 ((converting)) 规则在方法中编写自己的迭代器(它可以实现 java.util.iterator)并使用它。

    【讨论】:

    • 这也是我的答案 :) 编写一个 Iterator,它将 Iterator 作为构造函数参数,然后在 next() 方法中随时转换对象。跨度>
    【解决方案4】:

    您可以使用以下 sn-p :

    public static void main(String... args){
        Iterator<TypeA> iteratorTypeA = methodToGetIteratorTypeA();
        Iterator<TypeB> iteratorTypeB = new IteratorConveter<TypeA, TypeB>(iteratorTypeA,
            new Converter<TypeA, TypeB>(){
                public TypeB convert(TypeA typeA){
                    return null; //Something to convert typeA to type B
                }
            });
    }
    
    public class IteratorConveter<F, T> implements Iterator<T> {
        private final Converter<? super F, ? extends T> converter;
        private final Iterator<F> iterator;
    
        public IteratorConveter(Iterator<F> iterator, Converter<? super F, ? extends T> converter) {
            this.converter = converter;
            this.iterator = iterator;
        }
    
        public boolean hasNext() {
            return iterator.hasNext();
        }
    
        public T next() {
            return converter.convert(iterator.next());
        }
    
        public void remove() {
            iterator.remove();
        }
    }
    
    
    interface Converter<F, T> {
        T convert(F object);
    }
    

    【讨论】:

    • 对不起我不傻只是有点匆忙,在转换部分,我正在实例化一个新的 TypeB 实例并返回它。类似于: return new DictionaryEntry(doc.get("name").toString(), doc.get("id").toString());但我的堆空间用完了,这意味着这些实例没有被释放。 Iterator 来自数据库接口,因此它在内存中一次不会保存多个实例(我想)。我是在做一些愚蠢的事情还是完全取决于 TypeB 和它的迭代器?谢谢。
    【解决方案5】:

    由于 Java 中的泛型只是一个编译时构造,我觉得你最好在调用 next() 时强制转换每个检索到的元素,而不是强制转换迭代器。

    【讨论】:

      【解决方案6】:

      拥有一个它们共享的超类可能是个好主意,但这取决于这两种类型的定义方式,或者甚至可能让其中一种从另一种继承,因为它们似乎是两种表示对于相同的数据。这也将解决您的迭代器问题。

      或者您可以编写一个容器,该容器在内部使用其中一个进行数据访问,并且对外部世界具有流畅的表示。我指的是“组合优于继承”。

      但本质上,这一切都归结为:你是否认真考虑过你的班级结构?你确定它是最好的吗?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-03-22
        • 2012-05-24
        • 1970-01-01
        • 1970-01-01
        • 2020-02-25
        • 2012-11-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多