我有一些如下所示的搜索结果对象:
public class TradeSearchResult{
private String tradeRefNo;
private String relatedTradeId;
private String custodyDate;
private String orderNumber;
private String odrQty;
private String price : 500;
}
public class CollateralTradesSearchResult{
private String excludeTradeOUT;
private String settlementStatus;
private String fundId;
private String altFundId;
private String apNumber;
private String collateralOrderNumber;
private String componenetIdentifier;
}
现在我有一个搜索过滤条件对象
public class CRITERION {
protected String field; //The field denotes any field name of the either
SearchResult object
protected String operator; its will be EQUALS or NOT_EQUALS
protected String value; Value of the field.
}
现在,我需要编写一个动态过滤器方法,在该方法中,我将传递“条件”对象的列表,并可以传递如下所示的任一SearchResult的列表
public static List<Object> applyFilter(List<CRITERION> comp, List<?> objectList){
//The CRITERION.fiedName can be same in more than one in the list
return filteredList;
}
这是一个示例:考虑下面的
列表TradeSearchResult{
tradeRefNo : W12343;
relatedTradeId: N993093;
custodyDate : 2018-12-14;
orderNumber : 0000342343;
String odrQty : 12;
String price : 500;
},
{
tradeRefNo : W12344;
relatedTradeId: N993093;
custodyDate : 2018-12-14;
orderNumber : 0000342344;
String odrQty : 18;
String price : 600;
},
{
tradeRefNo : W12345;
relatedTradeId: N993094;
custodyDate : 2018-12-14;
orderNumber : 0000342345;
String odrQty : 20;
String price : 700;
}
Now the Criterion class is like
CRITERION{
field :relatedTradeId;
operator : EQUALS;
value :N993093;
}
{
field :relatedTradeId;
operator : EQUALS;
value :N993094;
}
{
field :orderNumber ;
operator : EQUALS;
value :0000342344;
}
即使relatedTradeId有两个过滤器,它也只会返回一个结果
TradeSearchResult{
tradeRefNo : W12344;
relatedTradeId: N993093;
custodyDate : 2018-12-14;
orderNumber : 0000342344;
String odrQty : 18;
String price : 600;
}
现在,在相同的applyFIlter方法中,我可以发送Criterion列表和CollateralTradesSearchResult列表,并返回过滤后的结果。 这是我尝试过的东西
public static List<Object> applyFilter(List<CRITERION> criList, List<?> objectList){
long startTime = Calendar.getInstance().getTimeInMillis();
Set<Object> objectSet = new HashSet<>();
for(CRITERION cri : criList){
String fieldName = cri.getFIELD();
objectList.stream().filter(p->beanProperties(p).get(fieldName).equals(cri.getVALUE())).forEachOrdered(objectSet::add);
//objectList.retainAll(objectSet);
//objectSet.clear();
}
List<Object> ret = new ArrayList<>(objectSet);
long endTime = Calendar.getInstance().getTimeInMillis();
System.out.println("Size"+ ret.size());
System.out.println("Time Taken to Search"+ String.valueOf(endTime-startTime));
return ret;
}
这是beanProperties()方法
public static Map<String, Object> beanProperties(Object bean) {
try {
Map<String, Object> map = new HashMap<>();
Arrays.asList(Introspector.getBeanInfo(bean.getClass(), Object.class)
.getPropertyDescriptors())
.stream()
// filter out properties with setters only
.filter(pd -> Objects.nonNull(pd.getReadMethod()))
.forEach(pd -> { // invoke method to get value
try {
Object value = pd.getReadMethod().invoke(bean);
if (value != null) {
map.put(pd.getName(), value);
}
} catch (Exception e) {
// add proper error handling here
}
});
return map;
} catch (IntrospectionException e) {
// and here, too
return Collections.emptyMap();
}
}
Any help using Stream or by any means will be helpful.
答案 0 :(得分:0)
创建一个接口SearchResult
,并让您的两个类都实现它。然后创建此类:
public class Filter<T extends SearchResult> {
public List<T> applyFilter(List<Criterion> criteria, List<T> list) {
Map<String, Set<String>> allowedValues = new HashMap<>();
Map<String, Set<String>> prohibitedValues = new HashMap<>();
populateValues(criteria, "EQUALS", allowedValues);
populateValues(criteria, "NOT_EQUALS", prohibitedValues);
prohibitedValues.forEach((k, v) -> list.removeIf(t -> v.contains(getFieldValue(k, t))));
allowedValues.forEach((k, v) -> list.removeIf(t -> !v.contains(getFieldValue(k, t))));
return list;
}
private static void populateValues(List<Criterion> criteria, String operator, Map<String, Set<String>> values) {
criteria.stream()
.filter(c -> c.getOperator().equals(operator))
.forEach(c -> {
values.merge(c.getField(), Stream.of(c.getValue()).collect(Collectors.toSet()),
(set1, set2) -> Stream.concat(set1.stream(), set2.stream()).collect(Collectors.toSet()));
});
}
private String getFieldValue(String fieldName, T object) {
Field field;
try {
field = object.getClass().getDeclaredField(fieldName);
} catch (NoSuchFieldException e) {
e.printStackTrace();
return null;
}
field.setAccessible(true);
try {
return (String) field.get(object);
} catch (IllegalAccessException e) {
e.printStackTrace();
return null;
}
}
}
并将其用作:
Filter<TradeSearchResult> filter = new Filter<>(); //or CollateralTradesSearchResult
List<TradeSearchResult> filteredList = filter.applyFilter(criteria, searchResults);