根据用户 choice/input 从 collection 中过滤 objects
Filtering objects from collection based on user choice/input
我有一个相当简单的练习,但我的知识和使用设计模式(+ 单元测试)的要求有限。该项目的目标是创建一个控制台应用程序,允许您保存(添加)、打印(显示全部)、删除(按 cryteria 删除)和过滤(按条件显示)来自 collection 的消息。
private String title;
private String author;
private String content;
private String creationDate;
我能够创建 "add" 函数和 "show all"。我的问题是过滤。我必须创建一个选项来根据用户给出的条件过滤保存 objects(所有可能的组合,如:按标题和创建日期过滤,按标题过滤等)。我考虑过使用如下开关和方法为用户提供从菜单中选择它的选项:
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());
}
但我认为复制大量相似的代码不是一个好习惯。另外,我将来可能会发现这样的解决方案会令人厌烦甚至不可能(每个新参数都会添加新的组合)。有更好的方法吗?比如选择条件 "one by one" 以便用户可以自己创建组合?我有一个提示,谓词可以帮助我解决这个问题,但我不知道该去哪里。
对于每个标准,您可以有一个 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
.
My problem is with the filtering. I must create an option to filter
saved objects based on the criteria given by the user (all possible
combinations like: filter by title and creationDate, filter by title
etc.).
这是您可以尝试、使用或即兴创作的东西。该代码是一个工作示例(使用 Java SE 8)。该示例具有 MessageFilter
class:
- 创建
List
个测试消息。
- 接受来自控制台的用户输入 - 消息字段及其值。例如,"title" 和 "message 1".
- 基于消息字段及其值从
getPredicate
方法。
- 谓词应用于消息并打印过滤结果。
该示例分别显示了 "title" 和 "author" 过滤器。我认为示例中的概念可以应用于其他过滤条件。
示例代码:
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;
}
}
我有一个相当简单的练习,但我的知识和使用设计模式(+ 单元测试)的要求有限。该项目的目标是创建一个控制台应用程序,允许您保存(添加)、打印(显示全部)、删除(按 cryteria 删除)和过滤(按条件显示)来自 collection 的消息。
private String title;
private String author;
private String content;
private String creationDate;
我能够创建 "add" 函数和 "show all"。我的问题是过滤。我必须创建一个选项来根据用户给出的条件过滤保存 objects(所有可能的组合,如:按标题和创建日期过滤,按标题过滤等)。我考虑过使用如下开关和方法为用户提供从菜单中选择它的选项:
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());
}
但我认为复制大量相似的代码不是一个好习惯。另外,我将来可能会发现这样的解决方案会令人厌烦甚至不可能(每个新参数都会添加新的组合)。有更好的方法吗?比如选择条件 "one by one" 以便用户可以自己创建组合?我有一个提示,谓词可以帮助我解决这个问题,但我不知道该去哪里。
对于每个标准,您可以有一个 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
.
My problem is with the filtering. I must create an option to filter saved objects based on the criteria given by the user (all possible combinations like: filter by title and creationDate, filter by title etc.).
这是您可以尝试、使用或即兴创作的东西。该代码是一个工作示例(使用 Java SE 8)。该示例具有 MessageFilter
class:
- 创建
List
个测试消息。 - 接受来自控制台的用户输入 - 消息字段及其值。例如,"title" 和 "message 1".
- 基于消息字段及其值从
getPredicate
方法。 - 谓词应用于消息并打印过滤结果。
该示例分别显示了 "title" 和 "author" 过滤器。我认为示例中的概念可以应用于其他过滤条件。
示例代码:
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;
}
}