对象排列问题

项目任务是要处理一个田径赛事的比赛结果。需要实现下面功能:
把某个比赛项目的成绩从高到低结果排序并在前面加上名次。成绩相同者名次相同,并按人名的字典(字母)顺序排序)。

比如本来结果的列表ArrayList<Result>输出如下:

成绩 名字
7.00 Donald Li
6.00 Joan Chen
7.00 Alan Jiang
4.00 Tricia Zhang
7.00 Ada Wang
6.00 William Sf

方法应该达到的理想效果如下
1 7.00 Ada Wang
1 7.00 Alan Jiang
1 7.00 Donald Li
4 6.00 Joan Chen
4 6.00 William Sf
6 4.00 Tricia Zhang

本人菜鸟,试了很多种方法都排不对,请能者大神不吝赐教指点迷津,非常感谢!

阅读 3.2k
5 个回答
public class Result {

    private Integer rank;

    private Double score;

    private String name;


    public Result(Double score, String name) {
        this.score = score;
        this.name = name;
    }

    public Double getScore() {
        return score;
    }

    public void setScore(Double score) {
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getRank() {
        return rank;
    }

    public void setRank(Integer rank) {
        this.rank = rank;
    }

    @Override
    public String toString() {
        return "Result{" +
                "rank=" + rank +
                ", score=" + score +
                ", name='" + name + '\'' +
                '}';
    }
}
@Test
    public void testSortedScoreJ8_1(){

        List<Result> results = Arrays.asList(
                new Result(7.00, "Donald Li"),
                new Result(6.00, "Joan Chen"),
                new Result(7.00, "Alan Jiang"),
                new Result(4.00, "Tricia Zhang"),
                new Result(7.00, "Ada Wang "),
                new Result(6.00, "William Sf")
        );

        // 根据分数进行分组并使用TreeMap进行排序,然后得到逆序视图
        NavigableMap<Double, List<Result>> navigableMap = results
                .stream()
                .collect(Collectors.groupingBy(Result::getScore, TreeMap::new, Collectors.toList()))
                .descendingMap();

        ArrayList<Result> rankList = new ArrayList<>(results.size());
        int rank = 1;

        for (Map.Entry<Double, List<Result>> entry : navigableMap.entrySet()) {

            // 根据名称进行排序并将设置排名
            int finalRank = rank;
            List<Result> resultList = entry.getValue().
                    stream()
                    .sorted(Comparator.comparing(Result::getName))
                    .peek(r -> r.setRank(finalRank))
                    .collect(Collectors.toList());

            rankList.addAll(resultList);

            rank += entry.getValue().size();
        }

        rankList.forEach(System.out::println);
    }

    @Test
    public void testSortedScoreJ8_2(){
        List<Result> results = Arrays.asList(
                new Result(7.00, "Donald Li"),
                new Result(6.00, "Joan Chen"),
                new Result(7.00, "Alan Jiang"),
                new Result(4.00, "Tricia Zhang"),
                new Result(7.00, "Ada Wang "),
                new Result(6.00, "William Sf")
        );

        // 把列表排序
        results.sort((s1,s2)->{
            // 分数从高到低
            int compareTo = s2.getScore().compareTo(s1.getScore());
            if(compareTo == 0){
                // 姓名从A到Z
                return s1.getName().compareTo(s2.getName());
            }
            return compareTo;
        });

        // 把分数从高到低进行排序
        List<Double> sortedScore = results
                .stream()
                .map(Result::getScore)
                .sorted(Comparator.reverseOrder())
                .collect(Collectors.toList());

        // 计算得到该分数的应该是第几名
        for (Result result : results) {
            result.setRank(sortedScore.indexOf(result.getScore())+1);
        }

        results.forEach(System.out::println);
    }

结果

Result{rank=1, score=7.0, name='Ada Wang '}
Result{rank=1, score=7.0, name='Alan Jiang'}
Result{rank=1, score=7.0, name='Donald Li'}
Result{rank=4, score=6.0, name='Joan Chen'}
Result{rank=4, score=6.0, name='William Sf'}
Result{rank=6, score=4.0, name='Tricia Zhang'}

Collections.sort(list, comparator) 进行排序
在覆写的sort方法中,先判断分数是否相同,如果相同则使用 for 循环遍历两个人名的每个位置上的字符直到某个位置上的字符有大小关系;如果不相同则直接返回成绩的大小关系。

题注想要的是这种效果吗?

public class Order {

    @Test
    public  void test() {
        List<Result> list = new ArrayList<>();
        list.add(new Order.Result(7.00, "Donald Li"));
        list.add(new Order.Result(6.00, "Joan Chen"));
        list.add(new Order.Result(7.00, "Alan Jiang"));
        list.add(new Order.Result(4.00, "Tricia Zhang"));
        list.add(new Order.Result(7.00, "Ada Wang"));
        list.add(new Order.Result(6.00, "William Sf"));

        Collections.sort(list);
                List<Result> list = Arrays.asList(
                new Result(6.00, "Joan Chen"),
                new Result(7.00, "Alan Jiang"),
                new Result(4.00, "Tricia Zhang"),
                new Result(7.00, "Ada Wang"),
                new Result(6.00, "William Sf"),
                new Result(6.00, "Will Sf"),
                new Result(1.00, "William PJ")
        );
        
        Collections.sort(list);
        double preNum = 0;
        for(int i = 0, count = 1,size = list.size();i < size;i++) {
            Result result = list.get(i);
            if(result.number != preNum) {
                count = i + 1;
                preNum = result.number;
            }
            System.out.println(count + ":" + result);
        }
    }

    public class Result implements Comparable<Result> {
        private Double number;
        private String name;

        public Result(Double number, String name) {
            this.number = number;
            this.name = name;
        }

        @Override
        public int compareTo(Result o) {
            int result = number.compareTo(o.number);

            if(result == 0) {
                result = -name.compareTo(o.name);
            }

            return -result;
        }

        @Override
        public String toString() {
            final StringBuilder sb = new StringBuilder("Result{");
            sb.append("number=").append(number);
            sb.append(", name='").append(name).append('\'');
            sb.append('}');
            return sb.toString();
        }
    }
}

`var arrayList = [{grade:7.00,name:'Donald Li'},
{grade:6.00,name:'Joan Chen'},
{grade:7.00,name:'Alan Jiang'},
{grade:4.00,name:'Tricia Zhang'},
{grade:7.00,name:'Ada Wang'},
{grade:6.00,name:'William Sf'}]

  function compare(propertyName) {
    return function(object1, object2) {
      var value1 = object1[propertyName];
      var value2 = object2[propertyName];
      if (value2 < value1) {
        return 1;
      } else if (value2 > value1) {
        return -1;
      } else {
        return 0;
      }
    }
  }
  arrayList.sort(compare("name"));`  

非常感谢回复!

现在我已经把结果列表按成绩高低和名字字母顺序排列好了,结果列表现在是resultList:

7.00 Ada Wang
7.00 Alan Jiang
7.00 Donald Li
6.00 Joan Chen
6.00 William Sf
4.00 Tricia Zhang

下面开始往结果前面加名次

int[] rank=new int[resultList.size()] ;
rank[0]=1;
for(int i=1; i<resultList.size();i++)

{if(resultList.get(i).getResultValue()==resultList.get(i-1).getResultValue())

{rank[i]=rank[i-1];}
else
{rank[i]=i+1;}

}

for(int i=0; i<resultList.size();i++) {
System.out.println(rank[i]+" "+resultList.get(i).getResultValue()+" "+resultList.get(i).getParticipant().getName()+" "+resultList.get(i).getParticipant().getTeam());
}

打印结果居然是:

1 7.00 Ada Wang
2 7.00 Alan Jiang
3 7.00 Donald Li
4 6.00 Joan Chen
5 6.00 William Sf
6 4.00 Tricia Zhang

很奇怪。当两项结果值相同时,怎么没有执行if结果把rank变为相同呢?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题