gpt4 book ai didi

java - 按作为输入给出的字段使用 Java 8 进行排序

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:38:08 26 4
gpt4 key购买 nike

我有一个 REST 端点,我希望 UI 传递他们想要按 “id”“name” 等对结果进行排序的字段名称。我想出了下面的方法,但实际上是在尝试使用反射/泛型,这样它就可以扩展到包含我项目中的每个对象。

如果我想为 100 个不同的类提供相同的功能,我觉得这个解决方案不容易维护。

public static void sort(List<MovieDTO> collection, String field) {
if(collection == null || collection.size() < 1 || field == null || field.isEmpty()) {
return;
}

switch(field.trim().toLowerCase()) {
case "id":
collection.sort(Comparator.comparing(MovieDTO::getId));
break;
case "name":
collection.sort(Comparator.comparing(MovieDTO::getName));
break;
case "year":
collection.sort(Comparator.comparing(MovieDTO::getYear));
break;
case "rating":
collection.sort(Comparator.comparing(MovieDTO::getRating));
break;
default:
collection.sort(Comparator.comparing(MovieDTO::getId));
break;
}
}

关于如何更好地实现它以便将其扩展为适用于几乎不需要维护的企业应用程序的任何想法?

最佳答案

原帖

我不会重复评论中所说的一切。那里有好的想法。我希望你明白反射不是这里的最佳选择。

我建议保留 Map<String, Function<MovieDTO, String>> ,其中键是 field名称,值为映射器movie -> field :

Map<String, Function<MovieDTO, String>> extractors = ImmutableMap.of(
"id", MovieDTO::getId,
"name", MovieDTO::getName
);

然后,集合可以这样排序:

Function<MovieDTO, String> extractor = extractors.getOrDefault(
field.trim().toLowerCase(),
MovieDTO::getId
);
collection.sort(Comparator.comparing(extractor));

玩反射

正如我所 promise 的,我正在添加我对注释处理的看法来帮助您。请注意,这不是您必须牢牢坚持的版本。这是一个很好的起点。

我声明了 2 个注释。

  • 阐明 getter 名称(如果未指定,<get + FieldName> 是模式):

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.FIELD})
    @interface FieldExtractor {

    String getterName();

    }
  • 为一个类定义所有可能的排序键:

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE})
    @interface SortingFields {

    String[] fields();

    }

类(class)MovieDTO已被赋予以下外观:

@SortingFields(fields = {"id", "name"})
class MovieDTO implements Comparable<MovieDTO> {

@FieldExtractor(getterName = "getIdentifier")
private Long id;
private String name;

public Long getIdentifier() {
return id;
}

public String getName() {
return name;
}

...

}

我没有更改 sort方法签名(虽然,它会简化任务):

public static <T> void sort(List<T> collection, String field) throws NoSuchMethodException, NoSuchFieldException {
if (collection == null || collection.isEmpty() || field == null || field.isEmpty()) {
return;
}

// get a generic type of the collection
Class<?> genericType = ActualGenericTypeExtractor.extractFromType(collection.getClass().getGenericSuperclass());

// get a key-extractor function
Function<T, Comparable<? super Object>> extractor = SortingKeyExtractor.extractFromClassByFieldName(genericType, field);

// sort
collection.sort(Comparator.comparing(extractor));
}

如您所见,我需要引入 2 个类来完成:

class ActualGenericTypeExtractor {

public static Class<?> extractFromType(Type type) {
// check if it is a waw type
if (!(type instanceof ParameterizedType)) {
throw new IllegalArgumentException("Raw type has been found! Specify a generic type for further scanning.");
}

// return the first generic type
return (Class<?>) ((ParameterizedType) type).getActualTypeArguments()[0];
}

}

class SortingKeyExtractor {

@SuppressWarnings("unchecked")
public static <T> Function<T, Comparable<? super Object>> extractFromClassByFieldName(Class<?> type, String fieldName) throws NoSuchFieldException, NoSuchMethodException {
// check if the fieldName is in allowed fields
validateFieldName(type, fieldName);

// fetch a key-extractor method
Method method = findExtractorForField(type, type.getDeclaredField(fieldName));

// form a Function with a method invocation inside
return (T instance) -> {
try {
return (Comparable<? super Object>) method.invoke(instance);
} catch (IllegalAccessException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
};
}

private static Method findExtractorForField(Class<?> type, Field field) throws NoSuchMethodException {
// generate the default name for a getter
String fieldName = "get" + StringUtil.capitalize(field.getName());

// override it if specified by the annotation
if (field.isAnnotationPresent(FieldExtractor.class)) {
fieldName = field.getAnnotation(FieldExtractor.class).getterName();
}

System.out.println("> Fetching a method with the name [" + fieldName + "]...");

return type.getDeclaredMethod(fieldName);
}

private static void validateFieldName(Class<?> type, String fieldName) {
if (!type.isAnnotationPresent(SortingFields.class)) {
throw new IllegalArgumentException("A list of sorting fields hasn't been specified!");
}

SortingFields annotation = type.getAnnotation(SortingFields.class);

for (String field : annotation.fields()) {
if (field.equals(fieldName)) {
System.out.println("> The given field name [" + fieldName + "] is allowed!");
return;
}
}

throw new IllegalArgumentException("The given field is not allowed to be a sorting key!");
}

}

它看起来有点复杂,但这是泛化的代价。当然,还有改进的余地,如果你指出来,我很乐意过来看看。

关于java - 按作为输入给出的字段使用 Java 8 进行排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45773795/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com