我有这个方法,效果不错,但是有没有更简洁的方法?
目前,我在地图上添加了比较器,并根据用户选择的值获得正确的比较器。
private Comparator<? super BusinessPartnerAssignmentDetail> getComparator(PortfolioFilterDto portfolioFilterDto){
Map<String, Comparator<? super BusinessPartnerAssignmentDetail>> sortingOptions = new HashMap<>();
sortingOptions.put("fieldOfficeDescription", Comparator.comparing(BusinessPartnerAssignmentDetail::getFieldOfficeDescription, Comparator.nullsLast(Comparator.naturalOrder())));
sortingOptions.put("locationDescription", Comparator.comparing(BusinessPartnerAssignmentDetail::getLocationDescription, Comparator.nullsLast(Comparator.reverseOrder())));
sortingOptions.put("segmentType", Comparator.comparing(BusinessPartnerAssignmentDetail::getSegmentType, Comparator.nullsLast(Comparator.reverseOrder())));
sortingOptions.put("displayName", Comparator.comparing(BusinessPartnerAssignmentDetail::getDisplayName, Comparator.nullsLast(Comparator.reverseOrder())));
return sortingOptions.get(portfolioFilterDto.getSortParameter());
}
然后我像这样在我的列表中调用排序器
businessPartnerAssignmentDetails.sort(getComparator(portfolioFilterDto));
我看到的唯一的捷径是自动转换 String
的方法表示。Function<? super BusinessPartnerAssignmentDetail, U>
使用反射。
重要的是。 这个解决方案可能在以下情况下有用 硕大 获取器的数量和可能的组合。获取器必须是无形式参数的(标准获取器)。我更倾向于坚持你目前的解决方案,这是更可读和可维护的方式,我认为这是优先考虑的。
解决方案和它的描述。
Method
来自 String
使用 Class::getMethod
.Function<? super BusinessPartnerAssignmentDetail, U>
从 Method
.Method::invoke
silentInv
)为了清晰起见。static List<String> naturalOrderList = Arrays.asList("fieldOfficeDescription");
static <U extends Comparable<U>> Comparator<? super BusinessPartnerAssignmentDetail>
getComparator(PortfolioFilterDto p) throws NoSuchMethodException
{
/** (1) **/
Method method = BusinessPartnerAssignmentDetail.class.getMethod(p.getSortParameter());
/** (2) **/
Function<? super BusinessPartnerAssignmentDetail, U> function = silentInv(method);
/** (3) **/
Comparator<U> order = methodsWithNaturalOrders.contains(method.getName())
? Comparator.naturalOrder()
: Comparator.reverseOrder();
return Comparator.comparing(function, Comparator.nullsLast(order));
}
@SuppressWarnings("unchecked")
static <U extends Comparable<U>> Function<? super BusinessPartnerAssignmentDetail, U>
silentInv(Method method)
{
/** (2) The necessary try-catch wrapping, the exception should never be thrown **/
return bpad -> {
try {
return (U) method.invoke(bpad);
} catch (Exception e) {
String message = "Invalid method name " + method.getName();
throw new IllegalArgumentException(message , e);
}
};
}
提示:如果可能的话,使用较短的类名。 如果可能的话,使用更短的类名:)
每次方法被调用时创建一个比较器的映射是一个坏主意。
相反,你可以在方法中返回所需的比较器。switch case
switch (portfolioFilterDto.getSortParameter()){
case "fieldOfficeDescription" :
return Comparator.comparing(BusinessPartnerAssignmentDetail::getFieldOfficeDescription, Comparator.nullsLast(Comparator.naturalOrder()));
case "locationDescription" :
return Comparator.comparing(BusinessPartnerAssignmentDetail::getLocationDescription, Comparator.nullsLast(Comparator.reverseOrder()));
case "segmentType" :
return Comparator.comparing(BusinessPartnerAssignmentDetail::getSegmentType, Comparator.nullsLast(Comparator.reverseOrder()));
case "displayName" :
return Comparator.comparing(BusinessPartnerAssignmentDetail::getDisplayName, Comparator.nullsLast(Comparator.reverseOrder()));
default :
return null;
}
或者你可以在构造函数里面创建地图作为一个全局字段,那么你就不会在每次撤销地图的时候初始化它。
试着使用一个ENUM作为排序选项,并使用一个开关案例来获得特定的比较器。
DTO与Enum过滤选项
public class PortfolioFilterDto {
/*your existing code
*
*
* */
PortfolioFilterDtoOptions sortParameter;
enum PortfolioFilterDtoOptions {
fieldOfficeDescription, locationDescription, segmentType, displayName
}
public PortfolioFilterDtoOptions getSortParameter() {
return this.sortParameter;
}
}
您的动态获取过滤器选项的方法
private Comparator<? super BusinessPartnerAssignmentDetail> getComparator(PortfolioFilterDto portfolioFilterDto) {
switch (PortfolioFilterDto.getSortParameter()) {
case PortfolioFilterDtoOptions.fieldOfficeDescription:
return Comparator.comparing(BusinessPartnerAssignmentDetail::getFieldOfficeDescription, Comparator.nullsLast(Comparator.naturalOrder()));
case PortfolioFilterDtoOptions.locationDescription:
return Comparator.comparing(BusinessPartnerAssignmentDetail::getLocationDescription, Comparator.nullsLast(Comparator.reverseOrder()));
case PortfolioFilterDtoOptions.segmentType:
return Comparator.comparing(BusinessPartnerAssignmentDetail::getSegmentType, Comparator.nullsLast(Comparator.reverseOrder()));
case PortfolioFilterDtoOptions.displayName:
return Comparator.comparing(BusinessPartnerAssignmentDetail::getDisplayName, Comparator.nullsLast(Comparator.reverseOrder()));
default:
// put default filter here
return null;
}
}
你可以把这些都包在一个 enum
就像Sourin说的那样,但你可以用更多的功能来丰富它,比如实际比较。
enum AssignmentFilter implements Comparator<BusinessPartnerAssignmentDetail> {
fieldOfficeDescription(BusinessPartnerAssignmentDetail::getFieldOfficeDescription, Comparator.naturalOrder()),
locationDescription(BusinessPartnerAssignmentDetail::getLocationDescription),
segmentType(BusinessPartnerAssignmentDetail::getSegmentType),
displayName(BusinessPartnerAssignmentDetail::getDisplayName);
private Function<BusinessPartnerAssignmentDetail, Comparable<? super BusinessPartnerAssignmentDetail>> compareByKey;
AssignmentFilter(Function<BusinessPartnerAssignmentDetail, Comparable<? super BusinessPartnerAssignmentDetail>> byKey, Comparator<BusinessPartnerAssignmentDetail> whenNull) {
compareByKey = Comparator.comparing(byKey, Comparator.nullsLast(whenNull));
}
AssignmentFilter(Function<BusinessPartnerAssignmentDetail, Comparable<? super BusinessPartnerAssignmentDetail>> byKey) {
this(byKey, Comparator.reverseOrder());
}
public int compare(BusinessPartnerAssignmentDetail bpad1, BusinessPartnerAssignmentDetail bpad1) {
return comparator().compare(bpad1, bpad2);
}
}
你可以通过以下方式调用它 businessPartnerAssignmentDetails.sort(AssingmentFilter.valueOf(portfolioFilterDto.getSortParameter()))
.
是否比单纯的填图好,由你决定。