我正在开发一个小应用程序,我试图将一个对象(Property
)放入ArrayList<Property>
。基本上我正在制作一个搜索功能,它在Map
搜索的内容上运行。
例如:我想搜索2013年至2015年间列出的名称为"12 Hello Lane"
的所有房产。
我会这样做:
for (Property p : properties){
if (p.getName().equals("12 Hello Lane") && p.getListingDate().getYear() >=2013 && p.getListingDate().getYear() <= 2015){
//Add to list
}
}
问题在于,我传递的Map
属性要进行比较,关键是方法名称,值是期望值。换句话说:
Key: "getName"
Value: "12 Hello Lane"
Key: "getYear"
Value: 2013-2015
...
我的问题是如何制作它以便我可以使用单个if语句来涵盖所有属性?类似的东西:
for (Property p : properties){
if (p.getClass().getMethod(options.getKey()) == options.getValue()){
//Add to list
}
}
我不知道我是否正确地表达了这一点,但我希望你们能让我的漂移。
编辑:我正在努力实现if a AND b AND c...
的效果。只是想我会澄清,因为我看到很多答案都提供了类似于OR
的内容。
答案 0 :(得分:1)
好的,因为所有的答案都试图做出魔术......这是我的建议。
您真正想要的是Matcher
每个匹配器看起来像这样......例如,匹配名称:
private static Matcher<Property> withName(final String name) {
return new BaseMatcher<Property>() {
public void describeTo(Description description) {
description.appendText("Matches property name to ").appendValue(name);
}
public boolean matches(Object o) {
Property p = (Property) o;
return p.name.equals(name);
}
};
}
然后您将拥有一些匹配器(用于地址,年份等)以及将所有这些标准应用于列表的实际过滤方法:
public List<Property> filter(Matcher<Property>... matchers) {
List<Property> valid = new ArrayList<Property>(); //valid ones to return
propertyLoop: for (Property property : propertyList) {
for (Matcher<Property> matcher : matchers) {
if (matcher.matches(property)) {
valid.add(property);
} else {
continue propertyLoop;
}
}
return valid;
}
因此,您的最终代码与此类似:
List<Property> machingProperties = filter(withName("12 Hello Lane"), withYear(2012, 2015));
答案 1 :(得分:0)
有时我只是想知道这些情况是如何存在的。 这是一般的想法:
for (Property p: properties) {
boolean shouldAdd = true;
for (String method: options.keySet()) {
if (p.getClass().getMethod(method).invoke(p) != options.get(key)) {
shouldAdd = false;
break;
}
}
if (shouldAdd) {
//add to list
}
}
答案 2 :(得分:0)
根据您的要求,听起来您需要的是某种谓词构建器。你需要编写一些代码来创建我在下面显示的这些谓词,然后你可以遍历它们并调用evaluate。我已经实现了你需要的一个案例。
force
和一个用于比较日期等。然后你可以调用你的for循环并在每个谓词上运行evaluate。
答案 3 :(得分:0)
你非常接近:
OR
,而不是AND
。如果你想要一个AND
,做一个标志,在循环中设置它,并在循环结束后检查它以下是您应该如何做到的:
List<Data> allItems = ...
List<Data> filtered = new ArrayList<>();
for (Data d : allItems) {
boolean allPass = true;
for (Map.Entry<String,String> entry : propertyMap.entrySet()) {
Method m = d.getClass().getMethod(entry.getKey());
if (m == null || !entry.getValue().equals(m.invoke(d))){
allPass = false;
break;
}
}
if (allPass) {
filtered.add(d);
}
}
答案 4 :(得分:0)
起初我很困惑,因为&#34; Property&#34;这个词的双关语。您可以创建另一个名为 PropertyAttribute 的类:
public class PropertyAttribute {
private String name;
private Object value;
public PropertyAttribute(String name, Object value) {
this.name = name;
this.value = value;
}
// Applicable getters and setters...
}
然后在 Property 中,您可以存储 PropertyAttributes 列表:
public class Property {
public List<PropertyAttribute> attributes = new ArrayList<PropertyAttribute>();
public Property() {
// Add to attributes, like:
attributes.add(new PropertyAttribute("name", "12 Hello Lane"));
attributes.add(new PropertyAttribute("year", "2013 - 2015"));
}
}
然后最后你可以搜索:
for(Property p : properties) {
for(PropertyAttribute attr : p.attributes) {
if(options.getKey() == attr.getName() && options.getValue() == attr.getValue) {
// add to list.
}
}
}