filtrar y ordenar la lista usando Google collections


Supongamos que tengo una lista (o Conjunto):

List<String> testList = Lists.newArrayList("assocX","srcT","destA","srcX", "don't care Y", "garbage", "srcB");

Me gustaría recuperar una lista inmutable(Set) que ordena/agrupa términos en orden natural donde los términos que comienzan con "src" son primero, "assoc" segundo y "dest" último. Si un término no los contiene, debe eliminarse de la lista resultante.

Por lo tanto, el resultado aquí es "srcB", "srcT", "assocX", "destA".

Creo que puedo hacer esto con alguna combinación de Iterables.filtrar o Predicados pero simplemente no verlo. Debe haber una forma sucinta de hacerlo, creo.

EDITAR: Un conjunto en lugar de una lista también funciona.

Author: harschware, 2010-02-22

4 answers

Mientras esos tres prefijos sean lo único que te importa, sugeriría algo como esto:

    Predicate<String> filter = new Predicate<String>() {
        @Override
        public boolean apply(String input) {
            return input.startsWith("src") || input.startsWith("assoc") || input.startsWith("dest");
        }
    };

    Function<String, Integer> assignWeights = new Function<String, Integer>() {
        @Override
        public Integer apply(String from) {
            if (from.startsWith("src")) {
                return 0;
            } else if (from.startsWith("assoc")) {
                return 1;
            } else if (from.startsWith("dest")) {
                return 2;
            } else {
                /* Shouldn't be possible but have to do something */
                throw new IllegalArgrumentException(from + " is not a valid argument");
            }
        }
    };

    ImmutableList<String> sortedFiltered = ImmutableList.copyOf(
            Ordering.natural().onResultOf(assignWeights).sortedCopy(
                    Iterables.filter(testList, filter)
            )
    );

Esta solución definitivamente no escalaría increíblemente bien si comienza a agregar más prefijos para filtrar o ordenar, ya que tendría que actualizar continuamente tanto el filtro como el peso de cada prefijo.

 33
Author: Paul Blessing,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-17 15:35:33

Echa un vistazo a Este ejemplo de Google Collections.

Function<Fruit, String> getNameFunction = new Function<Fruit, String>() {
    public String apply(Fruit from) {
        return from.getName();
    }
};

Ordering<Fruit> nameOrdering = Ordering.natural().onResultOf(getNameFunction);

ImmutableSortedSet<Fruit> sortedFruits = ImmutableSortedSet.orderedBy(
    nameOrdering).addAll(fruits).build();

Aunque esto, es cierto, devuelve un Conjunto.

 12
Author: extraneon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-22 17:57:29

Creo que primero tendrá que usar el predicado para eliminar elementos que no desea, y el implementar un Comparador y ordenar su lista.

 0
Author: Valentin Rocher,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-22 17:55:09

Por lo general, es un mal diseño recopilar datos claramente distintos como este. En su caso, cuando dice "assocX", "assoc" tiene un significado separado de "X", sin embargo, los fusiona.

Así que sugeriría diseñar una clase con dos campos. A continuación, puede crear un orden en el primer campo, otro en el segundo, y combinarlos (por ejemplo, Ordenar#compound()). Con un método toString () que hace fusionar estos campos en una cadena. Como beneficio adicional, esto puede reducir en gran medida el uso de memoria a través de compartir.

Así que estaría ordenando una lista de tales objetos, y si quisiera imprimirlos, simplemente llamaría a toString() sobre ellos.

 0
Author: Dimitris Andreou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-17 13:35:34