Filtrado de objetos de colección basada en la elección del usuario / entrada

DrAhzek:

Tengo un ejercicio bastante simple, pero estoy limitado por mi conocimiento y los requisitos a los patrones de uso de diseño (+ pruebas unitarias). El objetivo de un proyecto es crear una aplicación de consola que le permitirá ahorrar (ADD), imprimir (mostrar todos), remove (quitar por cryteria) y el filtro (mostrado por criterios) mensajes de la colección.

private String title;
private String author;
private String content;
private String creationDate;

Yo era capaz de crear la función "add" y "mostrar todos". Mi problema es con el filtrado. Debo crear una opción para los objetos de filtro guarda de acuerdo con los criterios dados por el usuario (todas las combinaciones posibles, como: Filtro por título y fechaCreacion, filtrar por título, etc.). Pensé en dar al usuario la opción de elegir desde el menú mediante el uso de interruptor y métodos de esta manera:

private final List<Message> storage = new ArrayList<Message>();

public List<Message> getAll() {
    final ArrayList<Message> messages = new ArrayList<>();
    messages.addAll(storage);
    return messages;
}
List<Message> find(String author) {
    return simpleStorage.getAll().stream()
        .filter(item -> item.getAuthor() == author)
        .collect(toList());
}

pero yo creo que no es una buena práctica para una gran cantidad de copias de un código similar. También, puede ser que me encuentro en el futuro que tal solución sería tedioso e incluso imposible (cada nuevo parámetro añadiría nuevas combinaciones). Hay una mejor manera de hacerlo? Al igual que la elección de un criterio de "uno por uno", por lo que los usuarios podrían crear una combinación por sí mismos? He tenido una punta que los predicados me podían ayudar con esto, pero no sé dónde ir con esto.

Andrew Tobilko:

Para cada criterio, usted podría tener un BiPredicate<String, Message>1 que tiene una entrada bruta de usuario y un mensaje, y le dice si el mensaje coincide con la opción de filtrado 2 .

Map<String, BiPredicate<String, Message>> criteria = Map.of(
        "title", (userTitle, message) -> input.equals(message.getTitle())
        ...
);

Te voy a dar un ejemplo simplificado de cómo ese mapa se puede utilizar:

Scanner scanner = new Scanner(System.in);

String filteringOption = scanner.nextLine();
String userInput = scanner.nextLine();

BiPredicate<String, Message> predicate = criteria.get(filteringOption);

// get all messages from the storage
getAll()  
        // make a stream out of them
        .stream()
        // apply the filtering rule from the map
        .filter(m -> predicate.test(userInput, m))  
         // collect them into a list to display
        .collect(Collectors.toList());

Más tarde, los predicados se pueden combinar por las operaciones lógicas como or(), and()para formar una opción de filtro personalizado. De que el usuario puede añadir al mapa para las llamadas consecuentes o calculado sobre la marcha cada vez que el usuario lo solicita, al igual

BiPredicate<String, Message> titleAndDateFilter = 
    criteria.get("title").and(criteria.get("date"));

1 Se puede usar un Predicate<Message>, pero sería hacer estas funciones menos aislados ya que se necesita para comparar contexto de un mensaje a la entrada dada.
2 Solía Java 9 de Map.of.

Supongo que te gusta

Origin http://43.154.161.224:23101/article/api/json?id=211398&siteId=1
Recomendado
Clasificación