POJO的"部分"排序列表

Xtr*_*mer 8 java sorting nested-loops java-8

我有List以下类的对象:

public class Foo {
    private Date date;
    private String name;
    private Long number;
}
Run Code Online (Sandbox Code Playgroud)

此列表是从数据库中获取的order by date asc, number desc,但是需要始终保留的部分是排序依据date asc.

结果示例(Dateformat = MM/dd/yyyy):

01/01/2016  Name1   928562
01/01/2016  Name2   910785
01/01/2016  Name3   811290
01/01/2016  Name4   811289
01/01/2016  Name5   5000000
02/01/2016  Name3   877702
02/01/2016  Name1   852960
02/01/2016  Name2   749640
02/01/2016  Name4   749500
02/01/2016  Name5   5000000
Run Code Online (Sandbox Code Playgroud)

现在我想订购该列表,以便它导致:

01/01/2016  Name2   910785
01/01/2016  Name1   928562
01/01/2016  Name3   811290
01/01/2016  Name4   811289
01/01/2016  Name5   5000000
02/01/2016  Name2   749640
02/01/2016  Name1   852960
02/01/2016  Name3   877702
02/01/2016  Name4   749500
02/01/2016  Name5   5000000
Run Code Online (Sandbox Code Playgroud)

如您所见,它现在按日期升序和名称排序.名称的顺序存储在另一个List(NameSortingList)中:

Name2
Name1
Name3
Run Code Online (Sandbox Code Playgroud)

注意,Name4并且Name5缺少NameSortingList,不能添加到它,因此应该在订购的所有内容之后添加.在有序列表之后的所有内容都可以有任何订单.

如果它变得更容易,那么lsit中没有的所有东西都可以合并为Foo每个唯一的日期,用name = "Other"它来汇总其中Numbers的所有元素.这样的结果的一个例子:

01/01/2016  Name2   910785
01/01/2016  Name1   928562
01/01/2016  Name3   811290
01/01/2016  Other   5811289
02/01/2016  Name2   749640
02/01/2016  Name1   852960
02/01/2016  Name3   877702
02/01/2016  Other   5749500
Run Code Online (Sandbox Code Playgroud)

我当前对此排序的方法是首先将所有日期提取为unqiue值,然后构建NameSortingList,然后迭代数据multipel次以按正确的顺序添加数据.我遇到的问题是

  1. 如果名称不存在,它可能会错过条目 NameSortingList
  2. 表现非常糟糕

dataFoo最上面描述的列表:

List<String> sortedNames = data.stream().filter(e -> e.getDate().equals(getCurrentMonthDate()))
        .map(e -> e.getName()).collect(Collectors.toCollection(ArrayList<String>::new));

Set<Date> uniqueDates = data.stream().map(e -> e.getDate())
        .collect(Collectors.toCollection(LinkedHashSet<Date>::new));

List<Foo> sortedFoo= new ArrayList<Foo>();
for (Date d : uniqueDates) {
    for (String name : sortedNames) {
        for (Foo fr : data) {
            if (fr.Date().equals(d) && fr.getName().equals(name)) {
                sortedFoo.add(fr);
                break;
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如何解决我描述的2个问题?也许甚至有一个流解决方案,我无法包裹我的头?


如果您有任何问题随时问

Kev*_*sen 4

如果我理解正确的话,您有一个来自数据库的列表,该列表date asc, number desc由于查询而默认排序。您现在想要对名称进行排序,date asc, name desc其中名称不是按字母顺序排序,而是根据它们在中的顺序nameSortingList(不在该列表中的名称将在最后排序)?

如果确实如此,那么如何:

myList.sort(Comparator.comparing(Foo::getDate)
                      .thenComparing(foo-> {
  int index = nameSortingList.indexOf(foo.getName());
  return i == -1 ? // If not found, it should be sorted as trailing instead of leading name
    Integer.MAX_VALUE
   : // Otherwise, sort it on the index in the nameSortingList:
    i;} ));
Run Code Online (Sandbox Code Playgroud)

编辑:正如@tobias_k在评论中正确指出的那样。最好首先为您创建一个 Map nameSortingList,其中 是names键, 中的索引nameSortingList是值。这对于性能来说会更好,因此您可以将其更改为:

myList.sort(Comparator.comparing(Foo::getDate)
                      .thenComparing(foo-> nameSortingMap.getOrDefault(foo.getName(), Integer.MAX_VALUE));
Run Code Online (Sandbox Code Playgroud)

尽管我怀疑这对于小列表来说会有那么大的影响。