繁体   English   中英

根据用户选择/输入过滤集合中的对象

[英]Filtering objects from collection based on user choice/input

我有一个相当简单的练习,但我受限于我的知识和使用设计模式的要求(+单元测试)。 项目的目标是创建一个控制台应用程序,允许您保存(添加),打印(显示全部),删除(通过冷冻删除)和过滤(按标准显示)来自集合的消息。

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

我能够创建“添加”功能和“显示所有”。 我的问题是过滤。 我必须创建一个选项,根据用户给出的条件过滤保存的对象(所有可能的组合,如:按标题过滤和创建日期,按标题过滤等)。 我想通过使用这样的开关和方法为用户提供从菜单中选择它的选项:

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());
}

但我认为复制大量类似的代码并不是一个好习惯。 此外,我可能会发现自己将来会发现这样的解决方案很烦人甚至不可能(每个新参数都会增加新的组合)。 有没有更好的方法呢? 就像“逐个”选择标准一样,用户可以自己创建组合吗? 我有一个提示,谓词可以帮助我这个,但我不知道该去哪里。

对于每个标准,您可以使用BiPredicate<String, Message> 1来获取用户的原始输入和消息,并告知消息是否与过滤选项2匹配。

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

我将为您提供一个如何使用该地图的简化示例:

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());

稍后,这些谓词可以通过逻辑运算(如or() and()以形成自定义过滤器选项。 用户的选项可以添加到地图中以用于后续呼叫,或者每次用户请求时即时计算,例如

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

1您可以使用Predicate<Message> ,但它会使这些函数不那么孤立,因为您需要将消息的上下文与给定的输入进行比较。
2我使用了Java 9的Map.of

我的问题是过滤。 我必须创建一个选项,根据用户给出的条件过滤保存的对象(所有可能的组合,如:按标题过滤和创建日期,按标题过滤等)。

这是你可以尝试,使用或即兴创作的东西。 代码是一个工作示例(使用Java SE 8)。 该示例具有MessageFilter类:

  • 创建测试消息List
  • 接受来自控制台的用户输入 - 消息字段及其值。 例如,“标题”和“消息1”。
  • 基于消息字段及其值从getPredicate方法获取Predicate
  • 谓词应用于消息并打印过滤结果。

该示例显示按“标题”和“作者”过滤 - 单独。 我认为示例中的概念可以应用于其他过滤条件。

示例代码:

class Message { // represents a message

    private String title;
    private String author;

    Message(String s1, String s2) {
        title = s1;
        author = s2;
    }

    String getTitle() {
        return title;
    }
    String getAuthor() {
        return author;
    }

    public String toString() {
        return String.join(", ", "("+title, author+ ")");
    }
}

public class MessageFilter {

    public static void main(String [] args) {

        // Create some messages

        Message [] array = {new Message("msg1", "auth1"),
                            new Message("msg2", "auth2"),
                            new Message("msg3", "auth1"),
                            new Message("msg9", "auth3")
                            };
        List<Message> messages = Arrays.asList(array);
        System.out.println(messages);

        // Accept user input: the field name and its value

        Scanner scanner = new Scanner(System.in);

        System.out.print("Enter the property to filter (title, author, etc): ");
        String filterCriteria = scanner.nextLine();
        System.out.print("Enter the property value: ");
        String filterValue = scanner.nextLine();

        // Get the predicate based on user input

        Predicate<Message> predicate = getPredicate(filterCriteria, filterValue);

        // Filter the data using the predicate got from user input, and print...

        List<Message> result = messages.stream()
                                        .filter(predicate)
                                        .collect(Collectors.toList());

        System.out.println("Result: " + result);
    }

    private static Predicate<Message> getPredicate(String criteria, String value) {

        Predicate<Message> p = msg -> true; // by default returns all messages

        switch(criteria) {
            case "title":
                p = msg -> msg.getTitle().equals(value);
                break;
            case "author":
                p = msg -> msg.getAuthor().equals(value);
                break;  
        }

        return p;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM