英文:
Lambda sort using Reflection
问题
我正在进行一个需要使用排序的类列表的项目,我有一个Lambda表达式,根据我需要排序的类的类型工作。排序发生在类本身的日期字段上:
Comparator<Class1> comparatorDescending = (exp1, exp2) -> exp2.getDate().compareTo(exp1.getDate());
this.classlist2sort.sort(comparatorDescending);
然而,我有两个,或许更多需要以这种方式排序的类,我决定将Lambda表达式移到父类并使其成为通用的。这需要一些工作,因为现在我需要将我正在处理的类的类型(Class1.class)传递到父类,然后进行通用排序。我尝试使用反射来实现以下内容:
Method m = this.typeParameterClass.getDeclaredMethod("getDate");
Comparator<T> comparatorDescending = (exp1, exp2) -> {
try {
return ((Comparable)m.invoke(exp2)).compareTo(m.invoke(exp1));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
};
this.classlist2sort((Comparator<? super T>) comparatorDescending);
这样做会给我一个错误消息:Unhandled exceptions: java.lang.IllegalAccessException, java.lang.reflect.InvocationTargetException
,我按照建议的解决方法尝试将表达式用try catch包围起来,如下所示:
Method[] input = this.typeParameterClass.getDeclaredMethods();
Method m = this.typeParameterClass.getDeclaredMethod("getDate");
Comparator<T> comparatorDescending = (exp1, exp2) -> {
try {
return ((Comparable)m.invoke(exp2)).compareTo(m.invoke(exp1));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
};
this.classlist2sort((Comparator<? super T>) comparatorDescending);
不幸的是,这样做会导致一个Cannot resolve method 'compareTo' in 'Object'
错误。我现在想知道我正在尝试做的是否可能。感谢任何帮助。
英文:
I'm working on a project that requires the use of sorted Class lists, and I have a lambda expression that worked according to the type of class I needed to be sorted. The sorting occurs on a date field of the class itself:
Comparator<Class1> comparatorDescending = (exp1, exp2) -> exp2.getDate().compareTo(exp1.getDate());
this.classlist2sort.sort(comparatorDescending);
However I have two, maybe more classes that need to be sorted in this way and I decided to move the lambda expression above to the parent class and make it a generic. This required a bit of work however in that I now need to pass into the parent class the type of class I'm dealing with (Class1.class), condition on that, then sort with generic. I tried the following using Reflection:
Method m = this.typeParameterClass.getDeclaredMethod("getDate");
Comparator<T> comparatorDescending = (exp1, exp2) ->
m.invoke(exp2).compareTo(m.invoke(exp1));
this.classlist2sort((Comparator<? super T>) comparatorDescending);
Doing so gave me an error message: Unhandled exceptions: java.lang.IllegalAccessException, java.lang.reflect.InvocationTargetException
to which I followed the suggested workaround of surrounding the expression with a try catch in the following manner:
Method[] input = this.typeParameterClass.getDeclaredMethods();
Method m = this.typeParameterClass.getDeclaredMethod("getDate");
Comparator<T> comparatorDescending = (exp1, exp2) -> {
try {
return m.invoke(exp2).compareTo(m.invoke(exp1));
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
this.classlist2sort((Comparator<? super T>) comparatorDescending);
Unfortunately, doin this resulted in a Cannot resolve method 'compareTo' in 'Object'
error. I am wondering now if what I'm trying to do is possible. Any help is appreciated
答案1
得分: 3
你可以将方法的返回值转换为 Comparable
(您需要确保 getDate
方法的返回值与此匹配)。比较器也可以使用 Comparator.comparing
进行简化。
try {
Method m = this.typeParameterClass.getDeclaredMethod("getDate");
this.classlist2sort.sort(Comparator.comparing(o -> {
try {
return (Comparable) m.invoke(o);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}).reversed());
} catch (NoSuchMethodException e) {
throw new RuntimeException(e); // or other handling
}
英文:
You can cast the return value of the method to Comparable
(you will have to make sure the return value of getDate
matches this). The comparator can also be simplified using Comparator.comparing
.
try {
Method m = this.typeParameterClass.getDeclaredMethod("getDate");
this.classlist2sort.sort(Comparator.comparing(o -> {
try {
return (Comparable) m.invoke(o);
} catch (IllegalAccessException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}).reversed());
} catch (NoSuchMethodException e) {
throw new RuntimeException(e); // or other handling
}
答案2
得分: 0
如果您可以访问Class1
、Class2
等类的源代码,您可以定义一个用于比较器的接口,从而完全避免使用反射。假设如下:
public interface HasDate {
LocalDate getDate();
}
我知道名称不好,但这个示例足够了。定义比较器以与HasDate
一起工作,然后您可以对实现了该接口的元素的列表进行排序。
public class RandomStuff {
public static void main(String[] args) {
Comparator<HasDate> dateComparator = (o1, o2) -> o2.getDate().compareTo(o1.getDate());
List<Class1> list1 = new ArrayList<>();
list1.add(new Class1(LocalDate.now()));
list1.add(new Class1(LocalDate.now().plusDays(1)));
list1.add(new Class1(LocalDate.now().minusDays(1)));
list1.sort(dateComparator);
System.out.println(list1);
List<Class2> list2 = new ArrayList<>();
list2.add(new Class2(LocalDate.now()));
list2.add(new Class2(LocalDate.now().plusDays(1)));
list2.add(new Class2(LocalDate.now().minusDays(1)));
list2.sort(dateComparator);
System.out.println(list2);
}
}
这样,您可以使用dateComparator
对list1
和list2
中的元素进行排序。
英文:
If you have access to the source code of Class1
, Class2
, etc. you can define an interface to be used for the comparator and avoid reflection altogether. Let's say:
public interface HasDate {
LocalDate getDate();
}
I know the name is bad, but it will do for an example. Define the comparator to work with HasDate
, and you can sort lists, whose elements implement the interface.
public class RandomStuff {
public static void main(String[] args) {
Comparator<HasDate> dateComparator = (o1, o2) -> o2.getDate().compareTo(o1.getDate());
List<Class1> list1 = new ArrayList<>();
list1.add(new Class1(LocalDate.now()));
list1.add(new Class1(LocalDate.now().plusDays(1)));
list1.add(new Class1(LocalDate.now().minusDays(1)));
list1.sort(dateComparator);
System.out.println(list1);
List<Class2> list2 = new ArrayList<>();
list2.add(new Class2(LocalDate.now()));
list2.add(new Class2(LocalDate.now().plusDays(1)));
list2.add(new Class2(LocalDate.now().minusDays(1)));
list2.sort(dateComparator);
System.out.println(list2);
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论