Saltar al contenido

¿Existe un método común de Java para recortar cada cadena en un gráfico de objetos?

Solución:

No, no hay un recorrido integrado para algo como esto, y recuerde que Java StringLos s son inmutables, por lo que en realidad no puede recortar en su lugar, debe recortar y reemplazar. Algunos objetos pueden no permitir la modificación de su String variables.

A continuación se muestra la explicación de la solución que he creado utilizando la API de reflexión de Java. He publicado el código de trabajo (con su URL en github) a continuación. Esta solución utiliza principalmente:

  1. API de reflexión de Java
  2. Manejo independiente de colecciones de Java
  3. Recursividad

Para empezar, he usado Introspector para repasar el readMethods de El Class omitiendo los métodos definidos para Object

for (PropertyDescriptor propertyDescriptor : Introspector
                    .getBeanInfo(c, Object.class).getPropertyDescriptors()) {
            Method method = propertyDescriptor.getReadMethod();

Casos

  1. Si el nivel actual de Property es de tipo String
  2. Si es un Object Matriz de propiedades
  3. Si es un String formación
  4. Si es un tipo de Java Collection clase
  5. Colocación separada para Map con condiciones especiales para procesar su teclas y valores

Esta utilidad utiliza la API de reflexión de Java para atravesar un gráfico de objetos con una sintaxis disciplinada de captadores y setters y recorta todas las cadenas encontradas dentro de un Object grafica de forma recursiva.

Código

Toda esta clase de utilidad con la clase de prueba principal (y tipos de datos personalizados / pojos) está aquí en mi github

Uso:

myObj = (MyObject) SpaceUtil.trimReflective(myObj);

Método util:

    public static Object trimReflective(Object object) throws Exception {
        if (object == null)
            return null;

        Class<? extends Object> c = object.getClass();
        try {
            // Introspector usage to pick the getters conveniently thereby
            // excluding the Object getters
            for (PropertyDescriptor propertyDescriptor : Introspector
                    .getBeanInfo(c, Object.class).getPropertyDescriptors()) {
                Method method = propertyDescriptor.getReadMethod();
                String name = method.getName();

                // If the current level of Property is of type String
                if (method.getReturnType().equals(String.class)) {
                    String property = (String) method.invoke(object);
                    if (property != null) {
                        Method setter = c.getMethod("set" + name.substring(3),
                                new Class<?>[] { String.class });
                        if (setter != null)
                            // Setter to trim and set the trimmed String value
                            setter.invoke(object, property.trim());
                    }
                }

                // If an Object Array of Properties - added additional check to
                // avoid getBytes returning a byte[] and process
                if (method.getReturnType().isArray()
                        && !method.getReturnType().isPrimitive()
                        && !method.getReturnType().equals(String[].class)
                        && !method.getReturnType().equals(byte[].class)) {
                    System.out.println(method.getReturnType());
                    // Type check for primitive arrays (would fail typecasting
                    // in case of int[], char[] etc)
                    if (method.invoke(object) instanceof Object[]) {
                        Object[] objectArray = (Object[]) method.invoke(object);
                        if (objectArray != null) {
                            for (Object obj : (Object[]) objectArray) {
                                // Recursively revisit with the current property
                                trimReflective(obj);
                            }
                        }
                    }
                }
                // If a String array
                if (method.getReturnType().equals(String[].class)) {
                    String[] propertyArray = (String[]) method.invoke(object);
                    if (propertyArray != null) {
                        Method setter = c.getMethod("set" + name.substring(3),
                                new Class<?>[] { String[].class });
                        if (setter != null) {
                            String[] modifiedArray = new String[propertyArray.length];
                            for (int i = 0; i < propertyArray.length; i++)
                                if (propertyArray[i] != null)
                                    modifiedArray[i] = propertyArray[i].trim();

                            // Explicit wrapping
                            setter.invoke(object,
                                    new Object[] { modifiedArray });
                        }
                    }
                }
                // Collections start
                if (Collection.class.isAssignableFrom(method.getReturnType())) {
                    Collection collectionProperty = (Collection) method
                            .invoke(object);
                    if (collectionProperty != null) {
                        for (int index = 0; index < collectionProperty.size(); index++) {
                            if (collectionProperty.toArray()[index] instanceof String) {
                                String element = (String) collectionProperty
                                        .toArray()[index];

                                if (element != null) {
                                    // Check if List was created with
                                    // Arrays.asList (non-resizable Array)
                                    if (collectionProperty instanceof List) {
                                        ((List) collectionProperty).set(index,
                                                element.trim());
                                    } else {
                                        collectionProperty.remove(element);
                                        collectionProperty.add(element.trim());
                                    }
                                }
                            } else {
                                // Recursively revisit with the current property
                                trimReflective(collectionProperty.toArray()[index]);
                            }
                        }
                    }
                }
                // Separate placement for Map with special conditions to process
                // keys and values
                if (method.getReturnType().equals(Map.class)) {
                    Map mapProperty = (Map) method.invoke(object);
                    if (mapProperty != null) {
                        // Keys
                        for (int index = 0; index < mapProperty.keySet().size(); index++) {
                            if (mapProperty.keySet().toArray()[index] instanceof String) {
                                String element = (String) mapProperty.keySet()
                                        .toArray()[index];
                                if (element != null) {
                                    mapProperty.put(element.trim(),
                                            mapProperty.get(element));
                                    mapProperty.remove(element);
                                }
                            } else {
                                // Recursively revisit with the current property
                                trimReflective(mapProperty.get(index));
                            }

                        }
                        // Values
                        for (Map.Entry entry : (Set<Map.Entry>) mapProperty
                                .entrySet()) {

                            if (entry.getValue() instanceof String) {
                                String element = (String) entry.getValue();
                                if (element != null) {
                                    entry.setValue(element.trim());
                                }
                            } else {
                                // Recursively revisit with the current property
                                trimReflective(entry.getValue());
                            }
                        }
                    }
                } else {// Catch a custom data type as property and send through
                        // recursion
                    Object property = (Object) method.invoke(object);
                    if (property != null) {
                        trimReflective(property);
                    }
                }
            }

        } catch (Exception e) {
            throw new Exception("Strings cannot be trimmed because: ", e);
        }

        return object;

    }

Prueba

También tengo una clase de prueba que crea un objeto relativamente complejo. La clase de prueba tiene diferentes escenarios que cubren:

  1. String propiedades
  2. Propiedades como tipos de datos personalizados que a su vez tienen String propiedades
  3. Propiedades como tipos de datos personalizados que a su vez tienen propiedades como tipos de datos personalizados que a su vez tienen String propiedades
  4. List de tipos de datos personalizados
  5. Set de Strings
  6. Array de tipos de datos personalizados
  7. Array de Strings
  8. Map de String y tipo de datos personalizados

Gráfico de objeto:

ingrese la descripción de la imagen aquí

Fragmento de código de objeto de prueba:

public static Music buildObj() {
        Song song1 = new Song();
        Song song2 = new Song();
        Song song3 = new Song();

    Artist artist1 = new Artist();
    Artist artist2 = new Artist();

    song1.setGenre("ROCK       ");
    song1.setSonnet("X    ");
    song1.setNotes("Y    ");
    song1.setCompostions(Arrays.asList(new String[] { "SOME X DATA  ",
            "SOME OTHER DATA X ", "SOME MORE DATA X    ", " " }));

    Set<String> instruments = new HashSet<String>();
    instruments.add("         GUITAR    ");
    instruments.add("         SITAR    ");
    instruments.add("         DRUMS    ");
    instruments.add("         BASS    ");

    song1.setInstruments(instruments);

    song2.setGenre("METAL       ");
    song2.setSonnet("A    ");
    song2.setNotes("B    ");
    song2.setCompostions(Arrays.asList(new String[] { "SOME Y DATA  ",
            "          SOME OTHER DATA Y ",
            "           SOME MORE DATA Y    ", " " }));

    song3.setGenre("POP       ");
    song3.setSonnet("DONT    ");
    song3.setNotes("KNOW     ");
    song3.setCompostions(Arrays.asList(new String[] { "SOME Z DATA  ",
            "               SOME OTHER DATA Z ",
            "          SOME MORE DATA Z   ", " " }));

    artist1.setSongList(Arrays.asList(new Song[] { song1, song3 }));

    artist2.setSongList(Arrays.asList(new Song[] { song1, song2, song3 }));
    Map<String, Person> artistMap = new HashMap<String, Person>();
    Person tutor1 = new Person();
    tutor1.setName("JOHN JACKSON DOE       ");
    artistMap.put("          Name                 ", tutor1);

    Person coach1 = new Person();
    coach1.setName("CARTER   ");
    artistMap.put("Coach      ", coach1);
    artist2.setTutor(artistMap);

    music.setSongs(Arrays.asList(new Song[] { song1, song2, song3 }));
    music.setArtists(Arrays.asList(new Artist[] { artist1, artist2 }));

    music.setLanguages(new String[] { "    ENGLISH    ", "FRENCH    ",
            "HINDI    " });
    Person singer1 = new Person();
    singer1.setName("DAVID      ");

    Person singer2 = new Person();
    singer2.setName("JACOB      ");
    music.setSingers(new Person[] { singer1, singer2 });

    Human man = new Human();
    Person p = new Person();
    p.setName("   JACK'S RAGING BULL   ");
    SomeGuy m = new SomeGuy();
    m.setPerson(p);
    man.setMan(m);

    music.setHuman(man);

    return music;
}

Salir:

#######BEFORE#######
>>[>>DAVID      ---<<, >>JACOB      ---<<]---[    ENGLISH    , FRENCH    , HINDI    ]---[>>ROCK       ---X    ---Y    ---[SOME X DATA  , SOME OTHER DATA X , SOME MORE DATA X    ,  ]---[         SITAR    ,          GUITAR    ,          BASS    ,          DRUMS    ]<<, >>METAL       ---A    ---B    ---[SOME Y DATA  ,           SOME OTHER DATA Y ,            SOME MORE DATA Y    ,  ]---<<, >>POP       ---DONT    ---KNOW     ---[SOME Z DATA  ,                SOME OTHER DATA Z ,           SOME MORE DATA Z   ,  ]---<<]---[>>---[>>ROCK       ---X    ---Y    ---[SOME X DATA  , SOME OTHER DATA X , SOME MORE DATA X    ,  ]---[         SITAR    ,          GUITAR    ,          BASS    ,          DRUMS    ]<<, >>POP       ---DONT    ---KNOW     ---[SOME Z DATA  ,                SOME OTHER DATA Z ,           SOME MORE DATA Z   ,  ]---<<]<<, >>{Coach      =>>CARTER    ---<<,           Name                 =>>JOHN JACKSON DOE       ---<<}---[>>ROCK       ---X    ---Y    ---[SOME X DATA  , SOME OTHER DATA X , SOME MORE DATA X    ,  ]---[         SITAR    ,          GUITAR    ,          BASS    ,          DRUMS    ]<<, >>METAL       ---A    ---B    ---[SOME Y DATA  ,           SOME OTHER DATA Y ,            SOME MORE DATA Y    ,  ]---<<, >>POP       ---DONT    ---KNOW     ---[SOME Z DATA  ,                SOME OTHER DATA Z ,           SOME MORE DATA Z   ,  ]---<<]<<]---=>   JACK'S RAGING BULL   <=<<
Number of spaces : 644
#######AFTER#######
>>[>>DAVID---<<, >>JACOB---<<]---[ENGLISH, FRENCH, HINDI]---[>>ROCK---X---Y---[SOME X DATA, SOME OTHER DATA X, SOME MORE DATA X, ]---[GUITAR, SITAR, DRUMS, BASS]<<, >>METAL---A---B---[SOME Y DATA, SOME OTHER DATA Y, SOME MORE DATA Y, ]---<<, >>POP---DONT---KNOW---[SOME Z DATA, SOME OTHER DATA Z, SOME MORE DATA Z, ]---<<]---[>>---[>>ROCK---X---Y---[SOME X DATA, SOME OTHER DATA X, SOME MORE DATA X, ]---[GUITAR, SITAR, DRUMS, BASS]<<, >>POP---DONT---KNOW---[SOME Z DATA, SOME OTHER DATA Z, SOME MORE DATA Z, ]---<<]<<, >>{Name=>>JOHN JACKSON DOE---<<, Coach=>>CARTER---<<}---[>>ROCK---X---Y---[SOME X DATA, SOME OTHER DATA X, SOME MORE DATA X, ]---[GUITAR, SITAR, DRUMS, BASS]<<, >>METAL---A---B---[SOME Y DATA, SOME OTHER DATA Y, SOME MORE DATA Y, ]---<<, >>POP---DONT---KNOW---[SOME Z DATA, SOME OTHER DATA Z, SOME MORE DATA Z, ]---<<]<<]---=>JACK'S RAGING BULL<=<<
Number of spaces : 111

Hay un recuento distinto de cero del número de espacios en el anterior recortado salida porque no hice un esfuerzo para anular toString de cualquier colecciónList, Set) o Map. Hay ciertas mejoras en el código que quiero hacer, pero para su caso, la solución debería funcionar bien.

Limitaciones (futuras mejoras)

  1. No se puede manejar la sintaxis indisciplinada de las propiedades (captadores / definidores no válidos)
  2. No se pueden gestionar colecciones encadenadas: por ejemplo, List<List<Person>> – debido al apoyo exclusivo a la convención de getters / setters disciplinados
  3. Sin soporte de biblioteca de colección de guayaba

Partiendo de @SwissArmyKnife, convertí su sencilla función de recorte de cadenas en una interfaz con un método predeterminado. Entonces, cualquier objeto donde le gustaría usar object.trim (), solo tiene que agregar “implements Trimmable”.

Interfaz de ajuste de cuerda simple: Trimmable.class

/**
 * Utility interface that trims all String fields of the implementing class.
 */
public interface Trimmable {

    /**
     * Trim all Strings
     */
    default void trim(){
        for (Field field : this.getClass().getDeclaredFields()) {
            try {
                field.setAccessible(true);
                Object value = field.get(this);
                if (value != null){
                    if (value instanceof String){
                        String trimmed = (String) value;
                        field.set(this, trimmed.trim());
                    }
                }
            } catch(Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Un objeto que nos gustaría que fuera recortable: Person.class (implementa la interfaz recortable)

public class Person implements Trimmable {
     private String firstName;
     private String lastName;
     private int age;

     // getters/setters omitted
}

Ahora puedes usar person.trim ()

Person person = new Person();
person.setFirstName("    John   ");
person.setLastName("  Doe");
person.setAge(30);
person.trim();
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *