如何在Java中使用另一个ID列表对列表进行排序

13

我有一个 Java 的对象列表,长得大概是这个样子:

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

我的视频对象看起来像这样:

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

我有另一个列表,其中只包含我的名称ID字符串:

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

如何编写一个 compareto 方法而不是通过比较每个视频来对我的视频列表进行排序,而是使用另一个列表?到目前为止,我的方法是使用简单的冒泡排序,但是随着我的列表变得越来越大,这将非常低效。

示例:

我可以拥有名称为“apple”,“bannana”,“orange”的视频对象

我用于排序的字符串列表可能是:“bannana”,“apple”,“orange”

因此,我要返回给客户端的视频应该按以下顺序排列:“bannana”,“apple”,“orange”


顺便说一下,我也在使用Java 7,所以无法使用流。 - DanielD
1
你能发一下样例输入/输出吗?我不确定我理解这个问题。 - Tunaki
你是基于“另一个列表”来定义顺序的吗?例如 {"新希望", "帝国反击战", "绝地归来"}? - rgettman
我已经在我的问题中添加了一个示例。@rgettman 是的,我是根据另一个列表定义顺序。对于混淆感到抱歉。 - DanielD
当你遇到排序定义中没有的“pear”时会发生什么? - rgettman
如果“pear”在我的字符串列表中,我希望跳过它,因为不存在名称ID为“pear”的视频。 - DanielD
6个回答

30

Java 8:

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

这个比这个小。


5
一个简单而清晰的解决方案,令人惊讶的是这还没有被提到过:
videos.sort(Ordering.explicit(nameIdList).onResultOf(Video::getNameId));

Ordering.explicit is part of Guava.


2

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());

2
您可以使用自定义比较器。
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());
     }
};

为了更加高效,你可以使用一个 Map<String, Integer>,这样你就能更加有效地查找所需的顺序。

2
除非相关的列表非常长,否则我会使用这个解决方案,但这里有一个替代方案,它具有时间复杂度为O(n)。任何使用ComparatorCollections.sortArrays.sort的解决方案其时间复杂度都不优于O(n log n)
该方法基于另一个列表对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);
}

以上代码仅在 List<String> list 已排序的情况下有效。 - Arpit Aggarwal

1
您可以使用Java 8的流。
List<Video> orderedList=
              nameIdList.stream()
                  .map(
                      s ->
                          videos.stream()
                              .filter(v -> v.get_id().equals(s))
                              .findFirst()
                              .orElse(null))
                  .collect(Collectors.toList());
              

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接