2010-03-07 46 views

Respuesta

0

Esa pregunta no se repite en la lista dos veces. Solo itera una vez y de lejos es el único método conocido.

También se podría utilizar algunas clases de transformadores en bienes comunes colecciones de Google-colecciones, pero todos ellos hacer lo mismo bajo el capó el siguiente :) siendo una forma

CollectionUtils.collect(collectionOfIntegers, new org.apache.commons.collections.functors.StringValueTransformer()); 
+0

No se repite la lista (al menos) dos veces; una vez en la lista original cuando se realiza la conversión y luego otra vez cuando se itera la lista de objetivos? –

0

Bueno, se podría crear su propio clase contenedora de iterador para hacer esto. Pero dudo que ahorres mucho haciendo esto.

Aquí hay un ejemplo simple que envuelve cualquier iterador a un iterador de cadena, usando Object.toString() para hacer la asignación.

public MyIterator implements Iterator<String> { 

    private Iterator<? extends Object> it; 

    public MyIterator(Iterator<? extends Object> it) { 
     this.it = it; 
    } 

    public boolean hasNext() { 
     return it.hasNext(); 
    } 

    public String next() { 
     return it.next().toString(); 
    } 

    public void remove() { 
     it.remove(); 
    } 
} 
2

Puede escribir un iterador de asignación que decora un iterador existente y aplica una función en él. En este caso, la función transforma los objetos de un tipo a otro "sobre la marcha".

Algo como esto:

import java.util.*; 

abstract class Transformer<T, U> implements Iterable<U>, Iterator<U> { 
    public abstract U apply(T object); 

    final Iterator<T> source;  
    Transformer(Iterable<T> source) { this.source = source.iterator(); } 

    @Override public boolean hasNext() { return source.hasNext(); } 
    @Override public U next()   { return apply(source.next()); } 
    @Override public void remove()  { source.remove(); } 

    public Iterator<U> iterator()  { return this; } 
} 

public class TransformingIterator { 
    public static void main(String args[]) { 
     List<String> list = Arrays.asList("1", "2", "3"); 
     Iterable<Integer> it = new Transformer<String, Integer>(list) { 
      @Override public Integer apply(String s) { 
       return Integer.parseInt(s); 
      } 
     }; 
     for (int i : it) { 
      System.out.println(i); 
     } 
    } 
} 
+0

Esto se parece a lo que estoy buscando. Según la respuesta similar, ¿hacer esto sobre la marcha me da mucha ventaja? –

+0

Honestamente, creo que la solución Google Collections (Ben Lings ') podría ser mejor. Su diseño es mucho más maduro y su implementación es más sólida. Francamente, acabo de descifrar ese código en 15 minutos sin pensarlo demasiado. – polygenelubricants

+1

Es decir, la clase implementa 'Iterator ' y 'Iterable '. No estoy seguro de si eso es kosher. – polygenelubricants

0

creo que habría ya sea que tenga que crear una lista personalizada (que implementa la interfaz de lista) o un iterador personalizado. Por ejemplo:

ArrayList<String> targetList = new ArrayList<String>(); 
ConvertingIterator<String> iterator = new ConvertingIterator<String>(targetList); 
// and here you would have to use a custom List implementation as a source List 
// using the Iterator created above 

Pero dudo que este enfoque pueda ahorrarle mucho.

12

Mi answer a esa pregunta se aplica a su caso:

import com.google.common.collect.Lists; 
import com.google.common.base.Functions 

List<Integer> integers = Arrays.asList(1, 2, 3, 4); 

List<String> strings = Lists.transform(integers, Functions.toStringFunction()); 

La lista transformado es una vista en la colección original, por lo que la transformación ocurre cuando se accede al destino List.

1

Lambdaj permite hacer eso de una manera muy simple y legible. Por ejemplo, suponiendo que tiene una lista de Entero y desea convertirlos en la representación de Cadena correspondiente, podría escribir algo así;

List<Integer> ints = asList(1, 2, 3, 4); 
Iterator<String> stringIterator = convertIterator(ints, new Converter<Integer, String> { 
    public String convert(Integer i) { return Integer.toString(i); } 
}); 

Lambdaj aplica la función de conversión solo mientras itera sobre el resultado. También hay una forma más concisa de usar la misma función. El siguiente ejemplo funciona suponiendo que tiene una lista de personas con una propiedad de nombre y desea convertir esa lista en un iterador de nombres de personas.

Iterator<String> namesIterator = convertIterator(persons, on(Person.class).getName()); 

Bastante fácil. ¿No es así?

8

Como alternativa a la iterador, se puede utilizar una clase asignador genérica, y sólo anular el método de la transformada:

  1. crear un asignador de colección genérica para cualquier tipo de datos
  2. [opcional] crear una biblioteca de métodos que transforman entre diferentes tipos de datos (y reemplazar el método)
  3. uso que biblioteca

la aplicación:

// Generic class to transform collections 
public abstract class CollectionTransformer<E, F> { 

    abstract F transform(E e); 

    public List<F> transform(List<E> list) { 
     List<F> newList = new ArrayList<F>(); 
     for (E e : list) { 
      newList.add(transform(e)); 
     } 
     return newList; 
    } 
} 

// Method that transform Integer to String 
// this override the transform method to specify the transformation 
public static List<String> mapIntegerToStringCollection(List<Integer> list) { 

    CollectionTransformer transformer = new CollectionTransformer<Integer, String>() { 
     @Override 
     String transform(Integer e) { 
      return e.toString(); 
     } 
    }; 
    return transformer.transform(list); 
} 

// Example Usage 
List<Integer> integers = Arrays.asList(1,2); 
List<String> strings = mapIntegerToStringCollection(integers); 

Esto sería útil si tiene que usar transformaciones todo el tiempo, encapsulando el proceso. Para que pueda hacer una biblioteca de mapeadores de colecciones muy fácil.

7

Java 8 vías:

List<String> original = ...; 
List<Wrapper> converted = original.stream().map(Wrapper::new).collect(Collectors.toList()); 

asumiendo Wrapper clase tiene un constructor de aceptar una String.

Cuestiones relacionadas