【问题标题】:How to use Java Comparator Interface to sort an Object list with reference to another list that has ids如何使用Java比较器接口参考另一个具有ID的列表对对象列表进行排序
【发布时间】:2014-12-10 07:08:39
【问题描述】:

我有一个名为 ArtWork 的实体,它有多个字段。

对于某些功能,我向 MySql 查询艺术品列表 - List<ArtWork> artworks。 我还有另一个 List 类型为 Long - List<Long> artworkIds

'artworks' 列表将包含属于 'artworksIds' 列表中任何 id 的对象,但与 'artworkIds' 中的顺序不同。

因此,我想参照列表'artworkIds' 中存在的ID 的顺序,按ID 对列表'artworks' 进行排序。

想使用Comparator 来实现这一点

谢谢

【问题讨论】:

  • 我建议实现一个比较器或创建一个 DTO,您可以在其中放置艺术品和 ID。
  • 谢谢 Riadh,你能分享一个关于如何使用比较器/创建 DTO 的 sn-p

标签: java list comparator


【解决方案1】:
class MYComparator implements Comparator<Artwork> {
  List<Long> artworkIds;
  MYComparator (List<Long> artworkIds) {
   this.artworkIds = artworkIds;
 }
 @Override
 public int compare(Artwork o1, Artwork o2) {
   int index1= artworkIds.indexOf(o1.getId());
   int index2 = artworkIds.indexOf(o2.getId());
   return (i1 < i2) ? -1 : ((i1 > i2) ? 1 : 0) ;
}

【讨论】:

  • 谢谢 Riadh,太棒了.. 那是一次蛋糕之旅......!
  • 不要忘记将构造函数名称 RefListComparator 更改为 MYComparator ...
  • @DirkNM - 谢谢,我已经做到了,并且可以正常工作..!
  • @KaushikShanmugamNagaraj 您确实意识到对indexOf 的每次调用都需要 O(n)(至少对于 List 的 ArrayList 和 LinkedList 实现而言)。这意味着整个排序算法将采用 O(n^2log(n)) 而不是 O(n log(n))。
【解决方案2】:

也许这对你有帮助,但也许有更有效的算法可以做到这一点:

public static class RefListComparator implements Comparator<Artwork> {

  List<Long> reflist;

  RefListComparator(List<Long> reflist) {
    this.reflist = reflist;
  }

  @Override
  public int compare(Artwork o1, Artwork o2) {
    for (long refid : reflist) {
      if (o1.id == refid) {
        return -1;
      }
      if (o2.id == refid) {
        return 1;
      }
    }
    return 0;
  }
}

【讨论】:

    【解决方案3】:

    我会将 Artwork 实例存储在 Map 中,其中键是 artworkID。
    然后,我将遍历 artworksID 列表,并按所需顺序按 ID 从 Map 中获取 Artworks。

    如果你坚持使用 Comparator 解决方案(我不推荐),你可以这样做:

    public int compare(ArtWork o1, ArtWork o2) {
    
        int i1 = listOfIDs.indexOf(o1.getID());
        int i2 = listOfIDs.indexOf(o2.getID());
        return (i1 < i2) ? -1 : ((i1 > i2) ? 1 : 0) ;
    }
    

    您应该添加对在 ID 列表中找不到艺术品 ID 的情况的处理。

    请注意,每次调用 indexOf 都会对您的 ID 列表进行线性搜索,这使得该解决方案在性能方面非常糟糕

    indexOf 的每个调用都需要O(n)(至少对于ListArrayListLinkedList 实现而言)。这意味着整个排序算法将采用O(n^2log(n)) 而不是O(n log(n))

    另一方面,按照我的建议创建地图并在 ID 列表上迭代一次需要 O(n)

    【讨论】:

    • 感谢 Eran,但为了提高效率,我们可以使用 Comparator Interface 来做到这一点吗?
    • @KaushikShanmugamNagaraj 我不确定使用比较器是否会更有效。如果您的比较器实例可以访问 ID 列表,您可以使用比较器来执行此操作。然后在 compare(o1,o2) 中,在 ID 列表中搜索 o1.getID() 是否在 o2.getID() 之前。
    • 我可以从我的 Comparator 实例访问 ID 列表。你能告诉我如何使用我的 idList 以及 sn-p 中的 compare() 方法,以便它帮助我吗?
    • @KaushikShanmugamNagaraj 编辑了我的答案,但我仍然不建议采用这种方法。
    • 谢谢,有帮助。不确定那是否是完美的。将保持此线程处于活动状态
    【解决方案4】:

    您可以使用 id 实现 Comparator 进行排序,如下所示

    public class ArtWorksIdComparator implements Comparator<ArtWork>{
    
        public int compare(ArtWork a1, ArtWork a2) {
    
            return (a1.getId() < a2.getId() ) ? -1: (a1.getId() > a2.getId() ) ? 1:0 ;
        }
    
    }
    

    了解Comparator和Comparable的区别可以查看this post in java geeks 希望这会有所帮助

    【讨论】:

      【解决方案5】:

      您可以在下面尝试。

      Collections.sort(artworks, new Comparator<ArtWork>() {
          public int compare(ArtWork left, ArtWork, right) {
              return Integer.compare(artworkIds.indexOf(left.getId()), listA.indexOf(left.getId()));
                  }
       });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-01-15
        • 2018-09-10
        • 2017-10-15
        • 2013-02-13
        • 2021-11-02
        • 2020-10-25
        相关资源
        最近更新 更多