Métodos creando una funcionalidad de transformación en colecciones -- java campo con type-safety campo con factory-method camp codereview Relacionados El problema

Methods creating transform functionality on Collections


10
vote

problema

Español

He escrito a unos pocos métodos en Java 8, y me pregunto qué se podría mejorar en aquellos:

  public static <E, R, C extends Collection<? extends R>> C transform(final Collection<E> collection, final Function<? super E, ? extends R> mapper) {     try {         Objects.requireNonNull(collection);         Objects.requireNonNull(mapper);         Class<? extends Collection> clazz = collection.getClass();         @SuppressWarnings("unchecked") Collection<Object> returnCollection = clazz.newInstance();         collection.stream().map(mapper).forEach(returnCollection::add);         @SuppressWarnings("unchecked") C genericReturnCollection = (C)returnCollection;         return genericReturnCollection;     } catch (InstantiationException | IllegalAccessException ex) {         throw new RuntimeException(ex);     } }  public static <E, R, C extends Collection<R>> C transform(final Collection<E> collection, final Function<? super E, ? extends R> mapper, final Supplier<C> collectionSupplier) {     Objects.requireNonNull(collection);     Objects.requireNonNull(mapper);     Objects.requireNonNull(collectionSupplier);     return collection.stream().map(mapper).collect(Collectors.toCollection(collectionSupplier)); }   

Su propósito es proporcionar una funcionalidad similar como el método 9988776665544331 , pero luego permitir que el tipo asignado difiere del tipo original. Por lo tanto, es algo que debería estar en una clase de fábrica 998877776655443322 , ya que siempre tendrá que crear una nueva colección.

algún código de ejemplo:

  LinkedList<Integer> linkedList = new LinkedList<>(); linkedList.add(5); linkedList.add(10); linkedList.add(15); LinkedList<String> resultList = transform(linkedList, i -> (i + 1) + "-" + i);   

y

  LinkedList<Integer> linkedList = new LinkedList<>(); linkedList.add(5); linkedList.add(10); linkedList.add(15); LinkedList<String> resultList = transform(linkedList, i -> (i + 1) + "-" + i, LinkedList::new);   

Ambos tienen como salida:

6-5
11-10
16-15

Soy consciente de que el transform con un Supplier<C>

Original en ingles

I have written a few simple-to-be-used methods in Java 8, and am wondering what could be improved upon those:

public static <E, R, C extends Collection<? extends R>> C transform(final Collection<E> collection, final Function<? super E, ? extends R> mapper) {     try {         Objects.requireNonNull(collection);         Objects.requireNonNull(mapper);         Class<? extends Collection> clazz = collection.getClass();         @SuppressWarnings("unchecked") Collection<Object> returnCollection = clazz.newInstance();         collection.stream().map(mapper).forEach(returnCollection::add);         @SuppressWarnings("unchecked") C genericReturnCollection = (C)returnCollection;         return genericReturnCollection;     } catch (InstantiationException | IllegalAccessException ex) {         throw new RuntimeException(ex);     } }  public static <E, R, C extends Collection<R>> C transform(final Collection<E> collection, final Function<? super E, ? extends R> mapper, final Supplier<C> collectionSupplier) {     Objects.requireNonNull(collection);     Objects.requireNonNull(mapper);     Objects.requireNonNull(collectionSupplier);     return collection.stream().map(mapper).collect(Collectors.toCollection(collectionSupplier)); } 

Their purpose is to provide similar functionality as the List.replaceAll() method, but then allowing that the mapped type differs from the original type. Hence it is something that should be in a static factory class, as it will always need to create a new collection.

Some example code:

LinkedList<Integer> linkedList = new LinkedList<>(); linkedList.add(5); linkedList.add(10); linkedList.add(15); LinkedList<String> resultList = transform(linkedList, i -> (i + 1) + "-" + i); 

and

LinkedList<Integer> linkedList = new LinkedList<>(); linkedList.add(5); linkedList.add(10); linkedList.add(15); LinkedList<String> resultList = transform(linkedList, i -> (i + 1) + "-" + i, LinkedList::new); 

Both have as output:

6-5
11-10
16-15

I am aware that the transform with a Supplier<C> as argument is obviously much nicer, however for convienience the single-argument version with only a function is much better.

        

Lista de respuestas

4
 
vote
vote
La mejor respuesta
 

Veo la opción menos proveedora como una muy rota. Considere el siguiente código:

  transform(linkedList.sublist(0, linkedList.size() / 2), i -> (i + 1) + "-" + i);   

O, cualquiera de las otras colecciones que no tienen un constructor predeterminado significativo:

  transform(Arrays.asList(argv), a -> a.toLowerCase());   

El código causará más dolores de cabeza de lo que el requisito pequeño para agregar el proveedor requerirá.

Los genéricos del mapeo también se rompen cuando no hay proveedor, porque el tipo real de la lista de retorno debe ser más específica ...

Perder el primer método estático.

El segundo método se ve bien, excepto el ordenamiento de los argumentos. Haría al proveedor el medio, no el último argumento (y presentaría algunas recién llegadas para que no lo hagas no tan largo de una línea):

  public static <E, R, C extends Collection<R>> C transform(           final Collection<E> collection,           final Supplier<C> collectionSupplier,           final Function<? super E, ? extends R> mapper) {     .... }   

La lectura lógica de ese orden es mejor, toma esta colección, mapea a esa colección y usa esta función para hacerlo ... Tal vez no sea un gran problema ...?

El caso de uso parece leer mejor para mí:

  List<String> lcargs = transform(Arrays.asList(args), ArrayList::new, a -> a.toLowerCase());   
 

I see the Supplier-less option as being a very broken one. Consider the following code:

transform(linkedList.sublist(0, linkedList.size() / 2), i -> (i + 1) + "-" + i); 

Or, any of the other collections that do not have a meaningful default constructor:

transform(Arrays.asList(argv), a -> a.toLowerCase()); 

The code will cause more headaches than the small requirement to add the supplier will require.

The Generics of the mapping are also broken when there is no supplier, because the actual type of the return list should be more specific....

Lose the first static method.

The second method looks fine, except for the ordering of the arguments. I would make the supplier the middle, not the last argument (and I would introduce some newlines to make it not-so-long-of-a-line):

public static <E, R, C extends Collection<R>> C transform(           final Collection<E> collection,           final Supplier<C> collectionSupplier,           final Function<? super E, ? extends R> mapper) {     .... } 

The logical reading of that order is better, take this collection, map to that collection, and use this function to do it..... maybe it is not such a big deal...?

The use-case seems to read better for me:

List<String> lcargs = transform(Arrays.asList(args), ArrayList::new, a -> a.toLowerCase()); 
 
 

Relacionados problema

3  Implementando una fábrica segura de hilo con almacenamiento en caché  ( Implementing a thread safe factory with caching ) 
Tengo un 9988776655544330 que crea Connector Objetos basados ​​en parámetros como URL, nombre de usuario y contraseñas. El Connector2 El objeto implem...

2  Reemplazo de iunitofwork con un patrón de fábrica  ( Replacing iunitofwork with a factory pattern ) 
Como seguimiento de este Blog Post y Esta pregunta , quería publicar mi idea de reemplazar el iunitofwork con un patrón de fábrica. Me parece que en el cas...

10  ¿Es este patrón de método de fábrica correcto?  ( Is this correct factory method pattern ) 
Sé que hay muchas preguntas similares, pero no entiendo la mayoría de esas preguntas porque no estoy seguro de si sé lo que es un patrón de método de fábrica....

6  Clase de elemento: crea copias de artículos predefinidos por nombre y devoluciones por puntero  ( Itemfactory class creates copies of predefined items by name and returns by po ) 
Estoy trabajando en escribir un juego de RPG basado en texto, y he decidido definir cada artículo posible como un archivo JSON en un directorio específico. La...

1  Creando objetos por nombre definido  ( Creating objects by defined name ) 
Estoy tratando de escribir un título universal creando objetos por nombre. Tengo un buen prototipo de trabajo ahora, pero debe haber una mejor manera que el c...

6  Patrón de fábrica simple para cocinar una pizza  ( Simple factory pattern for cooking a pizza ) 
He desarrollado una aplicación de línea de comandos que solicita al usuario que seleccione inicialmente un horno y luego solicita que cocinen una pizza. El ho...

7  Sistema de complemento de tiempo de compilación  ( Compile time plugin system ) 
Fondo Para una pieza de software que necesito para obtener extensible, quería diseñar un Sistema simple Tiempo de compilación "del complemento" en C ++. ...

5  Fábrica de mensajes  ( Message factory ) 
Hoy pensé en el patrón de diseño de fábrica en SWIFT, y hago una implementación con extensión. ¿Mi post se trata de que alguien tiene alguna observación o p...

4  Patrón de fábrica con controles  ( Factory pattern with controls ) 
He creado fábrica para crear controles de WPF. Tengo una cuerda con el nombre de control y lo mape para enumerar. Creo que es mala implementación del patrón d...

0  Selección de la clase de control en un ensamblador de documentos  ( Selecting control class in a document assembler ) 
Siento que hay una forma más limpia / más simple de hacer lo siguiente. ¿Hay un patrón de software existente que debería estar usando? Tengo una clase 9988...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos