java - Java 8 使用比较器和选项进行排序
问题描述
我正在尝试根据多个字段(其中一些字段在引用对象中)对对象列表进行排序。以下代码仅用于说明和示例目的,并非实际代码。AuthorBookStat 这是我要排序的对象(删除了获取器和设置器以增加可读性)
public class AuthorBookStat {
private String name;
private AuthorStats authorStats;
}
作者统计
public class AuthorStats {
private String genre;
private BookStats bookStats;
}
图书统计
public class BookStats {
Double averageBookRatings;
Integer pages;
String primaryMarket;
}
现在我想首先根据primaryMarket排序,然后是评分,然后是页面,最后是流派
这是我所做的,效果很好
public class AuthorTest {
public static void main(String args[]){
AuthorBookStat authorBookStat = new AuthorBookStat();
authorBookStat.setName("A");
AuthorStats authorStats = new AuthorStats();
authorStats.setGenre("fantasy");
BookStats bookStats = new BookStats();
bookStats.setAverageBookRatings(3.5d);
bookStats.setPages(100);
bookStats.setPrimaryMarket("US");
authorStats.setBookStats(bookStats);
authorBookStat.setAuthorStats(authorStats);
AuthorBookStat authorBookStat1 = new AuthorBookStat();
authorBookStat1.setName("A");
AuthorStats authorStats1 = new AuthorStats();
authorStats1.setGenre("sci-fi");
BookStats bookStats1 = new BookStats();
bookStats1.setAverageBookRatings(3.5d);
bookStats1.setPages(100);
bookStats1.setPrimaryMarket("DE");
authorStats1.setBookStats(bookStats1);
authorBookStat1.setAuthorStats(authorStats1);
List<AuthorBookStat> authorBookStatList = new ArrayList<>();
authorBookStatList.add(authorBookStat);
authorBookStatList.add(authorBookStat1);
Comparator<AuthorBookStat> sortByPrimaryMarket =
Comparator.comparing(a -> a.getAuthorStats().getBookStats().getPrimaryMarket());
Comparator<AuthorBookStat> sortByRatings =
Comparator.comparingDouble(a -> a.getAuthorStats().getBookStats().getAverageBookRatings());
Comparator<AuthorBookStat> sortByPages =
Comparator.comparingInt(a -> a.getAuthorStats().getBookStats().getPages());
Comparator<AuthorBookStat> sortByGenre =
Comparator.comparing(a -> a.getAuthorStats().getGenre());
var sortedList = authorBookStatList
.stream()
.sorted(
sortByPrimaryMarket.thenComparing(sortByRatings)
.thenComparing(sortByPages).thenComparing(sortByGenre)).collect(Collectors.toList());
// authorBookStatList.sort(sortByPrimaryMarket.thenComparing(sortByRatings)
// .thenComparing(sortByPages).thenComparing(sortByGenre));
// I can also sort based on the commented lines above. So both works
System.out.println(sortedList);
}
}
这工作正常,并给了我以下完美的输出
[AuthorBookStat{primaryMarket='DE', ratings=3.5, pages=100, genre=sci-fi},
AuthorBookStat{primaryMarket='US', ratings=3.5, pages=100, genre=fantasy}]
现在,假设有几个字段为空,并且我有可选的 getter。例如在 Bookstats 评级和 primaryMarket
public Optional<Double> getAverageBookRatings() {
return Optional.ofNullable(averageBookRatings);
}
public Optional<String> getPrimaryMarket() {
return Optional.ofNullable(primaryMarket);
}
如果有空余的字段首先被认为是一个而其他的不是,我将如何排序。例如,如果主要市场为空,则它获得最后优先级
[AuthorBookStat{primaryMarket='DE', ratings=3.5, pages=100, genre=sci-fi}, AuthorBookStat{ratings=3.5, pages=100, genre=fantasy}]
解决方案
使用Comparator.nullsFirst
or Comparator.nullsLast
,您可以指定用于比较键的空安全比较器,考虑到Optional
可以使用以下方法返回 null Optional.orElse(null)
:
Comparator<AuthorBookStat> sortByPrimaryMarket = Comparator
.comparing(a -> a.getAuthorStats().getBookStats().getPrimaryMarket().orElse(null), Comparator
.nullsFirst(String::compareTo));
Comparator<AuthorBookStat> sortByRatings = Comparator
.comparing(a -> a.getAuthorStats().getBookStats().getAverageBookRatings().orElse(null), Comparator
.nullsFirst(Double::compareTo));
推荐阅读
- powershell - Powershell 测量与网站的连接时间
- go - 如何让 go fasthttp 服务器在文件上传时更快地触发处理程序?
- numpy - Numpy - 线性代数
- c++ - 'operator<<' C++ 不匹配
- c - C程序中一些数组元素从函数内部更改为main函数内部
- windows - Windows gdal程序中cmd中的for循环
- python - 使用 Tensorflow Lite [Python/Flutter 集成] 获取正确的对象检测标签
- reactjs - console.log(this.props) 未定义
- python - 如何在编写时读取excel文件(Python)?
- java - 部署语句时如何在 Esper 8.5 中设置 StatementId/Statement Name