简体   繁体   English

使用Java中的Comparator对List进行排序

[英]Sorting on List using Comparator in Java

I have two class 我有两节课

public class PopularSports {    
    public int Rank;    
    public String Sport;
}

public class Medals {
    public String Sport    
    public String Medal    
    public int Year    
    public String Game    
    public String Athlete
}

When i try to lead their csv and get the result in List of each class, I want to sort them in following order. 当我尝试引导他们的csv并在每个类的List中获得结果时,我想按照以下顺序对它们进行排序。

The PopularSports class should sort in the following order: PopularSports类应按以下顺序排序:

  1. Rank
  2. Sport 运动

The Medals class should sort in the following order: Medals类应按以下顺序排序:

  1. Sport 运动
  2. Medal 勋章
  3. Year
  4. Game 游戏
  5. Athlete 运动员

I have created compactor like this 我已经创建了这样的压缩器

Collections.sort(medalReportList, new Comparator<Medals >() {
  @Override
  public int compare(Medals o1, Medals o2) {
   return getRankOfSportBySportName(o1.getSport()) > getRankOfSportBySportName(o2.getSport())
          ? +1
          : getRankOfSportBySportName(o1.getSport()) < getRankOfSportBySportName(o2.getSport())
          ? -1
          : o1.getAthlete().compareToIgnoreCase(o2.getAthlete());
    }
  });

But it is not making it happen, it sorts on athlete names. 但它没有实现它,它对运动员的名字进行排序。

You need to nest those checks. 您需要嵌套这些检查。 I'll write the PopularSports method and leave the other for you. 我会写出PopularSports方法,然后留给对方。

I'd recommend that you learn that Java coding standards and make those class names singular: PopularSport and Medal . 我建议你学习Java编码标准并使这些类名单数: PopularSportMedal I'll demonstrate below: 我将在下面演示:

public int compareTo(PopularSport other) {
    if (this.rank < other.rank) return -1;
    else if (this.rank > other.rank) return +1;
    else {
        // This is where the nesting happens to break the ties.
        if (this.sport.compareTo(other.sport) < 0) return -1;
        else if (this.sport.compareTo(other.sport) > 0) return +1;
        else return 0;  // You'll have deeper nesting for the other values in Medal.
    }
}

The order you choose determines which ones are checked first. 您选择的顺序决定首先检查哪些。 You nest in the else clause to break the ties. 你嵌套在else子句中以打破关系。

I would simplify you logic a bit. 我会简化你的逻辑。

public int compare(Medals o1, Medals o2) {
  int rankDifference = getRankOfSportBySportName(o1.getSport()) 
                             - getRankOfSportBySportName(o2.getSport());
  return rankDifference != 0 
      ? rankDifference
      : o1.getAthlete().compareToIgnoreCase(o2.getAthlete());
  }

Others already gave you a solution with ternary operator. 其他人已经为您提供了三元运算符的解决方案。 I, on the other hand, discourage you from using it in complicated situations - it's simply not readable and hard to maintain. 另一方面,我不鼓励你在复杂的情况下使用它 - 它根本不可读且难以维护。

Either go with if/else blocks (which will look pretty bad with so many fields to compare) or, even better, use a third party library. 要么使用if / else块(对于那么多要比较的字段看起来会很糟糕),或者更好的是,使用第三方库。 In Guava you can use ComparisionChain like this: Guava中你可以像这样使用ComparisionChain

new Comparator<Medals>() {
    @Override
    public int compare(Medals m1, Medals m1) {
        return ComparisonChain.start()
         .compare(m1.getSport(), m2.getSport())
         .compare(m1.getMedal(), m2.getMedal())
         .compare(m1.getYear(), m2.getYear())
         .compare(m1.getGame(), m2.getGame())
         .compare(m1.getAthlete(), m2.getAthlete(), String.CASE_INSENSITIVE_ORDER)
         .result();
    }
}

Isn't that more readable?! 这不是更具可读性吗?!

Sorting first list will no problem to you. 排序第一个列表对您没有问题。 If you want to sort as if sportName is same then sort according to medal and if medal name is same then sort according to year then solution is : 如果你想对sportName进行排序,那么根据奖牌进行排序,如果奖牌名称相同,则根据年份排序,然后解决方案是:

Best way: 最好的办法:

public void sortAccordingToAboveRequirement(List<Medal> medals){

 Collections.sort(medals,myComparator);

 }


  static Comparator<Medal> myComparator=new Comparator<Medal>() {
    @Override
        public int compare(Medal medal1, Medal medal2) {
        int value=0;
        value=medal1.getSport().compareTo(medal2.getSport());
        if(value!=0) return value;
        value=medal1.getMedal().compareTo(medal2.getMedal());
        if(value!=0) return value;
        value=medal1.getYear().compareTo(medal2.getYear());
        if(value!=0) return value;
        value=medal1.getGame().compareTo(medal2.getGame());
        if(value!=0) return value;
        value=medal1.getAthlete().compareTo(medal2.Athlete());
        return value;
    }
};

Use compareToIgnoreCase() if you wish :) 如果你愿意,可以使用compareToIgnoreCase():)

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

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