如何对List/ArrayList进行排序?

459

我有一个Java中的double列表,我想要按照降序排序ArrayList。

输入的ArrayList如下:

List<Double> testList = new ArrayList();

testList.add(0.5);
testList.add(0.2);
testList.add(0.9);
testList.add(0.1);
testList.add(0.1);
testList.add(0.1);
testList.add(0.54);
testList.add(0.71);
testList.add(0.71);
testList.add(0.71);
testList.add(0.92);
testList.add(0.12);
testList.add(0.65);
testList.add(0.34);
testList.add(0.62);

输出应该像这样

0.92
0.9
0.71
0.71
0.71
0.65
0.62
0.54
0.5
0.34
0.2
0.12
0.1
0.1
0.1

2
testList.sort(Comparator.reverseOrder()); - abbas
21个回答

667

74
或许值得一提的是,你可以定义自己的“比较器(Comparator)” :) - Polygnome
1
@Polygnome,原帖只是对“Double”进行排序。 - tckmn
5
是的,但是你可以根据使用情况以各种方式对它们进行排序。有时您可能希望按距离0的距离进行排序。我甚至不知道“reverse”的运行时特性,但是降序排序实际上可能比升序排序再反转要快。此外,使用支持Comparator作为构造函数参数的列表实现(从而保持其不变性)将确保列表始终排序。 - Polygnome
4
是的,Collections.sort在内部使用compareTo方法。 - tckmn
57
应该使用Collections.sort(list, Collections.reverseOrder());。除了更符合惯用语言(可能更有效),使用倒序比较器确保排序是“稳定的”(意思是当元素根据比较器相等时,它们的顺序不会被改变,而翻转则会改变它们的顺序)。 - Marco13
显示剩余7条评论

178

降序:

Collections.sort(mArrayList, new Comparator<CustomData>() {
    @Override
    public int compare(CustomData lhs, CustomData rhs) {
        // -1 - less than, 1 - greater than, 0 - equal, all inversed for descending
        return lhs.customInt > rhs.customInt ? -1 : (lhs.customInt < rhs.customInt) ? 1 : 0;
    }
});

1
如果CustomDataList<AnotherModel>,而AnotherModel具有id属性,我想按照id进行排序,那我该怎么办?而且我只能在我的类中访问CustomData模型。 - Dr.jacky
2
你只需要用AnotherModel替换CustomData类,并添加以下代码行:return lhs.id > rhs.id ? -1 : ..等等。 - user2808054
1
比较返回语句可以更好地编写为 Integer.compare(rhs.customInt, lhs.customInt); - LordKiz

155

对于你的示例,在Java 8中,这将起到神奇的作用。

List<Double> testList = new ArrayList();
testList.sort(Comparator.naturalOrder());

但如果你想按照正在排序的对象的某些字段进行排序,你可以轻松地实现以下操作:

testList.sort(Comparator.comparing(ClassName::getFieldName));
或者
 testList.sort(Comparator.comparing(ClassName::getFieldName).reversed());
或者
 testList.stream().sorted(Comparator.comparing(ClassName::getFieldName).reversed()).collect(Collectors.toList());

来源: https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html


1
你需要导入:import static java.util.Comparator.comparing; - krmanish007
1
它可用于Java 1.7吗? - lippo
5
不,这是Java 8中流和函数接口的一部分。 - krmanish007
1
你是对的 @AjahnCharles。他们已经移除了零参数,所以我现在已经更新了我的答案。 - krmanish007
你是对的@JonathanBenn,但我没有返回任何特定类型,所以在这种情况下,它将返回流。我的想法是展示在列表上进行排序的不同方法。关于你对testList.stream().sorted的评论,如果你除了排序还要做一些其他操作,那么打开一个流一起完成会更有用,而不是分成两个操作来完成。 - krmanish007
显示剩余6条评论

95

使用java.util.Collections类的util方法,例如

Collections.sort(list)

实际上,如果你想对自定义对象进行排序,可以使用

Collections.sort(List<T> list, Comparator<? super T> c) 

查看集合API


关于数组排序怎么样? - Jack

68
使用lambda表达式(Java 8),并将其简化为最简单的语法(在这种情况下,JVM会推断出很多),你可以得到:
Collections.sort(testList, (a, b) -> b.compareTo(a));

一个更冗长的版本:
// Implement a reverse-order Comparator by lambda function
Comparator<Double> comp = (Double a, Double b) -> {
    return b.compareTo(a);
};

Collections.sort(testList, comp);

使用lambda是可能的,因为Comparator接口只有一个方法需要实现,所以虚拟机可以推断出它正在实现哪个方法。由于参数的类型可以被推断出来,所以不需要声明,例如使用(a, b)而不是(Double a, Double b)。由于lambda体只有一行代码,并且期望方法返回一个值,所以return被推断出来,大括号也不是必需的。

这很酷,谢谢!这个更加紧凑:Collections.sort(testList, Comparator.reverseOrder()); - kavics
1
更加简洁:testList.sort(Comparator.reverseOrder()); - jonasespelita
你不需要compareTo方法。Collections.sort(testList, (a, b) -> b - a);可以达到同样的效果。 - Skillz

32

在Java8中,List接口提供了一个默认的sort方法,如果你提供了一个Comparator,它将允许你对集合进行排序。您可以按照以下方式轻松对问题中的示例进行排序:

testList.sort((a, b) -> Double.compare(b, a));
注意:传递给Double.compare的lambda中的参数已交换,以确保排序为降序。

对我来说,这是最好的答案,因为它也适用于使用对象进行排序...例如: locationDetails.sort((locationDetailAsc,locationDetailsDsc) -> Long.compare(locationDetailsDsc.getSnapshot().getQuantity(), locationDetailAsc.getSnapshot().getQuantity())); - Syed Anas
这个方法执行什么类型的排序? - Rishikrishna

32

这里是一个简短的备忘单,涵盖了典型情况:

import static java.util.Comparator.comparing;

// sort
list.sort(naturalOrder());

// sort (reversed)
list.sort(reverseOrder());

// sort by field
list.sort(comparing(Type::getField));

// sort by field (reversed)
list.sort(comparing(Type::getField).reversed());

// sort by int field
list.sort(comparingInt(Type::getIntField));

// sort by double field (reversed)
list.sort(comparingDouble(Type::getDoubleField).reversed());

// sort by nullable field (nulls last)
list.sort(comparing(Type::getNullableField, nullsLast(naturalOrder())));

// two-level sort
list.sort(comparing(Type::getField1).thenComparing(Type::getField2));

1
数组排序怎么样? - Jack

27

如果你的list包含可比较元素,那么可以使用Collections.sort(list)来对其进行排序。否则,我建议你像这样实现该接口:

public class Circle implements Comparable<Circle> {}

当然,您需要提供自己的compareTo方法实现,就像这样:

@Override
    public int compareTo(Circle another) {
        if (this.getD()<another.getD()){
            return -1;
        }else{
            return 1;
        }
    }

然后,您可以再次使用Colection.sort(list),因为现在列表包含Comparable类型的对象,并且可以进行排序。顺序取决于compareTo方法。有关更详细的信息,请查看https://docs.oracle.com/javase/tutorial/collections/interfaces/order.html


12

Collections.sort 允许您传递一个 Comparator 实例, 它定义了排序逻辑。所以,不必按自然顺序排序然后再反转,只需将Collections.reverseOrder() 传递给 sort 即可按相反的顺序对列表进行排序:

// import java.util.Collections;
Collections.sort(testList, Collections.reverseOrder());

正如@Marco13提到的那样,除了更符合习惯(可能更有效),使用相反顺序比较器确保排序是稳定的(意味着当元素根据比较器相等时,它们的顺序不会改变,而翻转则会改变顺序)


9
//Here is sorted List alphabetically with syncronized

package com.mnas.technology.automation.utility;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;

/**
 * @author manoj.kumar
 */
public class SynchronizedArrayList {
    static Logger log = Logger.getLogger(SynchronizedArrayList.class.getName());

    @SuppressWarnings("unchecked")
    public static void main(String[] args) {

        List<Employee> synchronizedList = Collections.synchronizedList(new ArrayList<Employee>());
        synchronizedList.add(new Employee("Aditya"));
        synchronizedList.add(new Employee("Siddharth"));
        synchronizedList.add(new Employee("Manoj"));
        Collections.sort(synchronizedList, new Comparator() {
            public int compare(Object synchronizedListOne, Object synchronizedListTwo) {
                //use instanceof to verify the references are indeed of the type in question
                return ((Employee) synchronizedListOne).name
                        .compareTo(((Employee) synchronizedListTwo).name);
            }
        }); 
    /*for( Employee sd : synchronizedList) {
    log.info("Sorted Synchronized Array List..."+sd.name);
    }*/

        // when iterating over a synchronized list, we need to synchronize access to the synchronized list
        synchronized (synchronizedList) {
            Iterator<Employee> iterator = synchronizedList.iterator();
            while (iterator.hasNext()) {
                log.info("Sorted Synchronized Array List Items: " + iterator.next().name);
            }
        }

    }
}

class Employee {
    String name;

    Employee(String name) {
        this.name = name;

    }
}

似乎Collections.synchronizedList可以帮助我们。 - vitalinvent

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接