如何使用两种排序对 ArrayList 进行排序 [英] How to sort an ArrayList using two sorts

查看:20
本文介绍了如何使用两种排序对 ArrayList 进行排序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含性别的名字列表,以及有多少人拥有这个名字.

I have a list of names that have the gender and a count of how many people have that name.

例如:

约翰 M 600

迈克 M 200

莎拉 F 700

汤姆 M 400

艾米丽 F 600

克里斯 M 600

我正在尝试按计数降序对名称进行排序,如果它们具有相同的计数,我希望它们按 ABC 顺序排序.我单独制作的函数按 ABC 顺序打印计数,然后按降序打印另一个.

I am trying to sort the names in descending order by the count and if they have the same count i want them to be sorted in ABC order. Function I made separately prints the count in ABC order and than prints another that is in descending order .

示例:发生了什么

克里斯 M 600

艾米丽 F 600

迈克 M 200

约翰 M 600

莎拉 F 700

汤姆 M 400

莎拉 F 700

约翰 M 600

艾米丽 F 600

克里斯 M 600

汤姆 M 400

迈克 M 200

我想得到什么

莎拉 F 700

克里斯 M 600

艾米丽 F 600

约翰 M 600

汤姆 M 400

迈克 M 200

ArrayList<OneName> oneName = new ArrayList<OneName>();
while(sc.hasNextLine())
    {

    // read a line from the input file via sc into line
        line = sc.nextLine();



        StringTokenizer stk = new StringTokenizer(line, ",");
        String name = stk.nextToken();
        char sex = stk.nextToken().charAt(0);
        int count = Integer.parseInt(stk.nextToken());


        OneName list = new OneName(name, sex, count);

        oneName.add(list);      



    }    Collections.sort(oneName, new OneNameCompare());

    for(OneName a: oneName)
    {
        System.out.println(a.toString());

    }
     Collections.sort(oneName, new OneNameCountCompare());
     for(OneName b: oneName)
    {

        System.out.println(b.toString());


     }

OneNameCompare.java

import java.util.Comparator;
import java.util.Collections;
public class OneNameCompare implements Comparator<OneName>
{

    public int compare(OneName a1, OneName a2)
    {
         return a1.getName().compareTo(a2.getName());
    }


 }

OneNameCountCompare.java

import java.util.Comparator;
import java.util.Collections;

public class OneNameCountCompare implements Comparator<OneName>
{
    {
     if(b1.getCount() < b2.getCount())
     {
        return 1;
     }
 else
 {
    return -1; 
 }
}
}

推荐答案

Java 8 解决方案

您可以通过 thenComparing(Comparator other) Java 8 中引入 Comparator 的方法.

Java 8 solution

You can combine both comparators via thenComparing(Comparator<? super T> other) method introduced to Comparator in Java 8.

所以代替

Collections.sort(oneName, new OneNameCompare());
for (OneName a : oneName) {
    System.out.println(a.toString());

}

Collections.sort(oneName, new OneNameCountCompare());
for (OneName b : oneName) {
    System.out.println(b.toString());
}

使用

Collections.sort(oneName, new OneNameCountCompare()
                              .thenComparing(new OneNameCompare()));
for (OneName b : oneName) {
    System.out.println(b.toString());
}

顺便说一句,您似乎可以简化"您的代码使用名为 方法参考的新 Java 8 功能一点点只需创建所需的比较器.

BTW it seems that you can "simplify" your code a little using new Java 8 features called method references to simply create required Comparators.

import static java.util.Comparator.comparing;

//...

Comparator<OneName> reversedCountComparator = comparing(OneName::getCount).reversed();
Comparator<OneName> nameComparator = comparing(OneName::getName);

oneName.sort(reversedCountComparator.thenComparing(nameComparator));

oneName.forEach(System.out::println);


Java 7 解决方案.

因为 Collections.sort(collection,comparator) 只接受一个比较器,所以你需要创建一个类来实现 Comparator,但会在内部使用你的其他比较器.这样的类的代码可以是这样的


Java 7 solution.

Since Collections.sort(collection, comparator) accept only one comparator you need to create class which will implement Comparator, but will internally use your other comparators. Code of such class can look like

class ComparatorsMixer<T> implements Comparator<T> {
    List<Comparator<T>> comparatorsList;

    public ComparatorsMixer(List<Comparator<T>> list) {
        this.comparatorsList = list;
    }

    public ComparatorsMixer() {
        comparatorsList = new ArrayList<>();
    }

    public void addComparator(Comparator<T> comparator){
        comparatorsList.add(comparator);
    }
    
    public int compare(T o1, T o2) {
        for (Comparator<T> c : comparatorsList) {
            int result = c.compare(o1, o2);
            if (result != 0)
                return result;
            //if result == 0 then move on to next comparator
        }
        return 0;
    }
}

你可以像这样使用它

ComparatorsMixer<OneName> mix = new ComparatorsMixer<>();
mix.addComparator(new OneNameCountCompare());
mix.addComparator(new OneNameCompare());

Collections.sort(oneName, mix);

这篇关于如何使用两种排序对 ArrayList 进行排序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆