我有这段代码,显然它看起来不太好--似乎所有的if--都是可以避免的。
if(sortBy.equals("firstName"))
personList.sort(Comparator.comparing(Person::getFirstName));
else if(sortBy.equals("lastName"))
personList.sort(Comparator.comparing(Person::getLastName));
else if(sortBy.equals("age"))
personList.sort(Comparator.comparing(Person::getAge));
else if(sortBy.equals("city"))
personList.sort(Comparator.comparing(Person::getCity));
else if(sortBy.equals("state"))
personList.sort(Comparator.comparing(Person::getState));
else if(sortBy.equals("zipCode"))
personList.sort(Comparator.comparing(Person::getZipCode));
该函数接受sortBy
,它是Person
属性之一的名称,并根据该字段对personList
应用排序。我如何避免如果-否则,写一个更好看的,可能的一行代码?
目前,我发现可以使用HashMap在字段名和相应的比较器之间创建映射。
map.put("age", Comparator.comparing(Person::getAge));
map.put("firstName", Comparator.comparing(Person::getFirstName))
...
并使用personList.sort(map.get(sortBy))
。
但是仍然觉得它可以在不需要额外步骤的情况下得到进一步的改进,直到它遵循开放-封闭原则,并且在Person
中添加一个新的字段将不需要我们修改代码。我在找类似的东西
personList.sort(Comparator.comparing(Person::getterOfField(sortBy)))
更新-1
现在,我决定坚持使用Map<String, Function<Person, Comparable<?>>
,我不喜欢考虑基于反射的解决方案。但我仍然在搜索是否可以找到类似于这的方法,其中排序是一个参数。
更新-2
我认为单行不是一个好的解决方案,因为如果其中一个字段不实现比较器,您就不会得到编译时错误。
发布于 2022-08-28 07:13:06
假设编译时知道sortBy
值和相应的getter,这将是使用字符串switch
语句的好地方:
Function<Person.String> getter = null;
switch (sortBy) {
case "firstName":
getter = Person::getFirstName; break;
case "lastName":
getter = Person::getLastName; break;
...
}
personList.sort(Comparator.comparing(getter));
如果使用Java的最新版本(Java12及更高版本),则可以使用switch
表达式而不是switch
语句。
Function<Person.String> getter;
getter = switch (sortBy) {
case "firstName" -> Person::getFirstName;
case "lastName" -> Person::getLastName;
...
default -> null;
}
personList.sort(Comparator.comparing(getter));
注意:在处理sortBy
值不被识别的情况时,您应该做得更好(比我的代码不可靠)。
发布于 2022-08-27 22:50:31
正如keshlam所建议的,我认为使用反射API是对您的问题最好的合适答案,但请记住,在生产代码中使用它通常是不鼓励的。
注意:如果您添加了一个新的Person
-attribute (它本身不是Comparable
),那么您将不得不使用自定义的Comparator
。考虑到这一点,您可能希望保留您已经拥有的Map<String, Comparator<?>>
解决方案。
https://stackoverflow.com/questions/73516275
复制