【问题标题】:Sorting ArrayList by multiple properties按多个属性对 ArrayList 进行排序
【发布时间】:2015-05-04 08:06:19
【问题描述】:

我有一个ArrayListof 玩家,其属性为字符串类型的username 和长类型的winratio,这只是gameswon/gamesplayed*100 的比率。

我想通过usernameArrayList 进行排序,我已经使用Comparator 类完成了该操作,但是我还想创建另一种方法来对基于winratio 的玩家进行排序,如果他们有相等的@987654329 @ 以他们的username 对它们进行排序。我不确定如何将两个比较器组合在一起并赋予它们一个层次结构,以便它知道哪种类型优先于另一个。

谢谢

【问题讨论】:

  • 您可以在单个比较器中完成这两件事。只需在单个 compareTo 方法中添加这两个东西'

标签: java sorting arraylist comparator


【解决方案1】:

计算winRatio的差异,如果是0,返回名称的差异,例如...

public class MultiComparator implements Comparator<Player> {

    @Override
    public int compare(Player o1, Player o2) {
        int result = (int) (o1.getWinRatio() - o2.getWinRatio());
        if (result == 0) {
            result = o1.getUserName().compareTo(o2.getUserName());
        }
        return result;
    }

}

因为我无事可做,所以我用了这个

public interface Player {
    public String getUserName();
    public long getWinRatio();
}

作为基础对象

另一个(奇怪的)想法可能是创建一个“链接的”Comparator,允许您将两个(或更多)Comparator 链接在一起,这样任何一个Comparator 的结果都是@ 987654328@,它将继续尝试将值与列表中的Comparator 进行比较...

public class RatioComparator implements Comparator<Player> {

    @Override
    public int compare(Player o1, Player o2) {
        return (int) (o1.getWinRatio() - o2.getWinRatio());
    }

}

public class NameComparator implements Comparator<Player> {

    @Override
    public int compare(Player o1, Player o2) {
        return o1.getUserName().compareTo(o2.getUserName());
    }

}

public class ChainedComparator implements Comparator<Player> {

    private Comparator<Player>[] comparators;

    public ChainedComparator(Comparator<Player>... comparators) {
        this.comparators = comparators;
    }

    @Override
    public int compare(Player o1, Player o2) {
        int result = -1;
        for (Comparator<Player> proxy : comparators) {
            result = proxy.compare(o1, o2);
            if (result != 0) {
                break;
            }
        }
        return result;
    }
}

你可以使用类似...

Collections.sort(list, new ChainedComparator(new RatioComparator(), new NameComparator()));

这是未经测试的,只是一个粗略的想法;)

【讨论】:

    【解决方案2】:

    你想要的可以在 compare 方法中使用下面的代码来实现,

    int compare(T o1, T o2){
       if(o1.winratio < o2.winratio){
          return -1;
       }else if(o1.winratio < o2.winratio){
          return +1;
       }else{
         return o1.userName.compareTo(o2.userName);
       }
    }
    

    这应该可行,我建议实现 Comparable 接口来处理默认排序情况...

    【讨论】:

      【解决方案3】:

      如果他们有相同的赢率来按照他们的用户名排序

      这表示您应该使用 userName 来实现comparable(用于自然排序)。对于 winRatio,请使用 comparator,如果 winRatio 相同 - 还要检查他们的用户名。

      【讨论】:

      • @downvoter,您可以等待编辑完成后再投宝贵的一票。
      猜你喜欢
      • 2011-05-17
      • 2013-06-14
      • 2011-03-21
      • 2011-05-13
      • 1970-01-01
      • 2011-02-16
      • 2012-08-05
      相关资源
      最近更新 更多