Filtro e la lista di ordinamento mediante raccolte di Google
Domanda
Supponiamo che io ho una lista (o Set):
List<String> testList = Lists.newArrayList("assocX","srcT","destA","srcX", "don't care Y", "garbage", "srcB");
Mi piacerebbe tornare un ImmutableList (Set) che ordina / gruppi di termini in ordine naturale in cui i termini che iniziano con "src" sono in primo luogo, "assoc" seconda e "dest" ultima. Se un termine non contiene quelle allora dovrebbe essere rimosso dalla lista risultante.
Quindi il risultato qui è "srcB", "srcT", "assocX", "Desta".
Credo di poter fare questo con una certa combinazione di Iterables.filter o predicati, ma semplicemente non vederlo. Ci deve essere un modo succinto di farlo credo.
EDIT:. Un set al posto di una lista funziona così
Soluzione
Finché queste tre prefissi sono le uniche cose che ti interessano, io suggerirei qualcosa di simile:
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)
)
);
Questa soluzione sicuramente non sarebbe scale out incredibilmente bene se si inizia ad aggiungere più prefissi per filtrare o ordinare da, dal momento che avrebbe dovuto aggiornare continuamente sia il filtro e il peso di ogni prefisso.
Altri suggerimenti
Dai un'occhiata alla Questa Google Collezioni esempio .
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();
Anche se questo, è vero, restituisce un set.
Credo che si dovrà prima di utilizzare il predicato per eliminare gli elementi che non si desidera, e l'attuazione di una comparatore e ordinare la vostra lista.
Di solito è cattivo design per raccogliere dati nettamente distinte come questo. Nel tuo caso, quando si dice "assocX", "assoc" ha un significato distinto da "X", eppure si fondono insieme.
Quindi, vorrei suggerire la progettazione di una classe con due campi. Quindi è possibile creare un ordinamento sul primo campo, un altro sulla seconda, e combinarli (ad esempio Ordinamento # composto ()). Con un metodo toString () che ha unire questi campi in una stringa. Come bonus, questo può ridurre notevolmente l'utilizzo della memoria attraverso la condivisione.
Quindi, si sarebbe ordinamento di un elenco di tali oggetti, e se si voleva di stamparli, si sarebbe solo chiamare toString () su di loro.