简体   繁体   English

如何通过另一个 id 列表对 java 中的列表进行排序

[英]How can I sort a list in java by another list of ids

I have a list of objects in java that looks something like this:我有一个 java 中的对象列表,看起来像这样:

List<Video> videos = new ArrayList<Video>();

and my video object looks like this:我的视频对象如下所示:

public class Video {
    private String nameId;
    private Integer id;
    ...
}

I have another list that just has my nameId strings:我有另一个列表,其中只有我的 nameId 字符串:

List<String> nameIdList = ArrayList<String>();

How can I write a compareto method that doesn't sort my list of videos by comparing each video and instead uses another list?如何编写一个 compareto 方法,该方法不会通过比较每个视频来对我的视频列表进行排序,而是使用另一个列表? My approach so far has been to use a simple bubble sort but that will be very inefficient as my list gets bigger到目前为止,我的方法是使用简单的冒泡排序,但随着我的列表变大,这将非常低效

Example:例子:

I could have video objects with nameIds : "apple", "bannana", "orange"我可以拥有 nameIds 的视频对象:“apple”、“bannana”、“orange”

and my list of strings to sort them by could be: "bannana", "apple", "orange"我用来排序的字符串列表可能是:“bannana”、“apple”、“orange”

so my videos I would want to return to my client should be in the order of: "bannana", "apple", "orange"所以我想返回给我的客户的视频应该按以下顺序排列:“bannana”、“apple”、“orange”

Java 8:爪哇 8:

videos.sort(Comparator.comparing(v->nameIdList.indexOf(v.getNameId())));

this is smaller than this这比

A simple and clean solution, which surprisingly has not been mentioned:一个简单而干净的解决方案,令人惊讶的是没有提到:

videos.sort(Ordering.explicit(nameIdList).onResultOf(Video::getNameId));

Ordering.explicit is part of Guava. Ordering.explicit是 Guava 的一部分。

You could use a custom Comparator您可以使用自定义比较器

List<String> nameIdList = new ArrayList<>();
Comparator<Video> compare = new Comparator<Video>() {
     public int compare(Video v1, Video v2) {
         return nameIdList.indexOf(v1.getNameId()) - nameIdList.indexOf(v2.getNameId());
     }
};

To make this more efficient you could have a Map<String, Integer> so you can look up the desired order more efficiently.为了提高效率,您可以使用Map<String, Integer>以便更有效地查找所需的顺序。

Unless the lists involved are very long, I would use this solution, but here is an alternative solution that has time complexity O(n) .除非涉及的列表长,否则我会使用这个解决方案,但这里有一个时间复杂度为O(n)的替代解决方案。 Any solution using a Comparator together with Collections.sort or Arrays.sort has time complexity no better than O(n log n) .任何使用ComparatorCollections.sortArrays.sort解决方案的时间复杂度都不比O(n log n)

The method sorts the list videos based on the other list, and clears away any Video whose nameId is not in the list.该方法根据另一个列表对列表videos排序,并清除nameId不在列表中的任何Video

public static void sort(List<Video> videos, List<String> list) {
    Map<String, List<Video>> map = new HashMap<>();
    for (String string : list)
        map.put(string, new ArrayList<>());
    for (Video video : videos) {
        List<Video> value = map.get(video.getNameId());
        if (value != null)
            value.add(video);
    }
    videos.clear();
    for (String string : list)
        for (Video video : map.get(string))
            videos.add(video);
}

Java 8. Convert to map and pick by hash: Java 8. 转换为 map 并通过哈希选择:

Map<String, Video> videoMap = videos.stream()
         .collect(Collectors.toMap(Video::getNameId, v -> v));

return videos.stream()
         .map(v -> videoMap.get(v))
         .collect(Collectors.toList());

You can use Java 8 stream您可以使用 Java 8 流

List<Video> orderedList=
              nameIdList.stream()
                  .map(
                      s ->
                          videos.stream()
                              .filter(v -> v.get_id().equals(s))
                              .findFirst()
                              .orElse(null))
                  .collect(Collectors.toList());
              

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM