parsa
parsa

Reputation: 2668

Converting Iterator types in Java

I have an Iterator<TypeA> that I want to convert to Iterator<TypeB>. TypeA and TypeB cannot be directly cast to each other but I can write a rule how to cast them. How can I accomplish this? Should I extend and override Iterator<TypeA>'s next, hasNext and remove methods?

Upvotes: 9

Views: 8447

Answers (6)

Kajetan Abt
Kajetan Abt

Reputation: 1545

It might be a good idea to have a super-class which they share, but that depends on how exactly those two types are defined, or possibly even have one of them inherit from the other, as it seems they are two representations for the same data. That would also solve your iterator issues.

Or you could write a container which internally uses one of them for data access and has a sleek representation to the outside world. I refer to "Composition over Inheritance".

But in essence, it all comes down to: Have you thought very hard about your class structure? Are you sure it's as good as it can be?

Upvotes: 1

Aboelnour
Aboelnour

Reputation: 1435

I guess you should write your own iterator(it can implements java.util.iterator) with your ((converting)) rule in a method and use it.

Upvotes: 3

GaryF
GaryF

Reputation: 24340

You don't need to write this yourself. Guava (formerly Google-collections) has you covered in Iterators.transform(...)

You provide your iterator and a function that converts TypeA to TypeB and you're done.

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;
   }
});

Upvotes: 22

Colin Hebert
Colin Hebert

Reputation: 93167

You can use the following snippet :

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);
}

Upvotes: 2

anirvan
anirvan

Reputation: 4877

Since Generics in Java is just a compile time construct, I feel you'll be better off casting each element you retrieve on invoking next() than to cast the iterators.

Upvotes: 1

Boris Pavlović
Boris Pavlović

Reputation: 64632

Write an adapter. Here's an example in Java. OReilly's book 'Head First: Design Patterns' gives the best explanation on the topic.

Upvotes: 7

Related Questions