简体   繁体   中英

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:

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:

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? 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"

and my list of strings to sort them by could be: "bannana", "apple", "orange"

so my videos I would want to return to my client should be in the order of: "bannana", "apple", "orange"

Java 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.

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.

Unless the lists involved are very long, I would use this solution, but here is an alternative solution that has time complexity O(n) . Any solution using a Comparator together with Collections.sort or Arrays.sort has time complexity no better than 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.

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:

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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