Java集合sort()

时间:2020-02-23 14:36:27  来源:igfitidea点击:

今天,我们将研究Java Collections的排序方法。
在Java中使用Collections时,我们不仅仅需要对数据进行排序。

Java集合sort()

Java Collections类为我们提供了一个非常方便的方法Collections.sort()来对所有List实现(例如LinkedList和ArrayList)进行排序。

有两个重载的Collections.sort()方法,它们是:

  • sort(List list):按照其自然顺序的升序对List的元素进行排序。

  • sort(List list,Comparator c):根据比较器产生的顺序对列表中的元素进行排序。

请注意,上述方法签名使用了泛型,但为了简化阅读,此处已将其删除。
让我们一个一个地探讨如何以及何时使用这两种方法。

Java Collections排序(列表)

考虑一下StringArrayList

List<String> fruits = new ArrayList<String>();
fruits.add("Apple");
fruits.add("Orange");
fruits.add("Banana");
fruits.add("Grape");

现在,我们将使用Collections.sort()对它进行排序:

Collections.sort(fruits);
//Print the sorted list
System.out.println(fruits);

该程序的输出为:

[Apple, Banana, Grape, Orange]

因此,我们可以看到Collections.sort()已按词汇顺序对String列表进行了排序。
它不返回任何东西。

如果我们有一个自定义对象列表,该怎么办?当然,我们也可以对它们进行排序。
考虑一类水果:

package com.theitroad.collections;
public class Fruit{
  private int id;
  private String name;
  private String taste;

  Fruit(int id, String name, String taste){
      this.id=id;
      this.name=name;
      this.taste=taste;
  }
}

让我们创建一个水果列表:

List<Fruit> fruitList=new ArrayList<Fruit>();
Fruit apple=new Fruit(1, "Apple", "Sweet");
Fruit orange=new Fruit(2, "Orange", "Sour");
Fruit banana=new Fruit(4, "Banana", "Sweet");
Fruit grape=new Fruit(3, "Grape", "Sweet and Sour");

fruitList.add(apple);
fruitList.add(orange);
fruitList.add(banana);
fruitList.add(grape);

为了对该列表进行排序,如果我们直接使用Collections.sort(List list),则会出现"编译时错误",因为没有为Fruit对象定义自然排序。
因此,它不知道如何对该列表进行排序。

为了使对象具有自然顺序,它们必须实现接口java.lang.Comparable。

"可比较"接口具有方法" compareTo()",该方法将返回负数,0;如果当前值分别小于,等于或者大于我们要比较的值,则返回正数。

让我们增强Fruit类,以实现"可比较"接口。
我们定义自然排序的顺序是基于Fruit的" id"字段:

package com.theitroad.collections;
public class Fruit implements Comparable<Object>{
  private int id;
  private String name;
  private String taste;

  Fruit(int id, String name, String taste){
      this.id=id;
      this.name=name;
      this.taste=taste;
  }
  @Override 
  public int compareTo(Object o) {
      Fruit f = (Fruit) o; 
      return this.id - f.id ;
  }
}

现在我们已经实现了Comparable,我们可以对列表进行排序而不会出现任何错误:

Collections.sort(fruitList);
fruitList.forEach(fruit -> {
  System.out.println(fruit.getId() + " " + fruit.getName() + " " + 
    fruit.getTaste());
});

输出将如下所示:

1 Apple Sweet
2 Orange Sour
3 Grape Sweet and Sour
4 Banana Sweet

Java集合排序(列表列表,比较器c)

为了定义一种不同于元素自然排序的自定义逻辑,我们可以实现java.util.Comparator接口,并将其实例作为sort()的第二个参数传递。

让我们考虑我们要基于"水果"的"名称"字段定义排序。
我们实现了"比较器",并在其"比较"方法中,需要编写比较逻辑:

package com.theitroad.collections;

class SortByName implements Comparator<Fruit> {
  @Override
  public int compare(Fruit a, Fruit b) {
      return a.getName().compareTo(b.getName());
  }
}

现在,我们可以使用以下比较器对其进行排序:

Collections.sort(fruitList, new SortByName());

输出将如下所示:

1 Apple Sweet
4 Banana Sweet
3 Grape Sweet and Sour
2 Orange Sour

除了使用lambda函数编写新的Comparator类外,我们还可以在运行时提供排序逻辑:

Collections.sort(fruitList, (a, b) -> {
  return a.getName().compareTo(b.getName());
});

Java Collections.reverseOrder

默认情况下,Collection.sort以升序执行排序。
如果我们想以相反的顺序对元素进行排序,则可以使用以下方法:

  • reverseOrder():返回一个Comparator,它强加了集合元素自然排序的顺序。

  • reverseOrder(Comparator cmp):返回一个" Comparator",对指定的比较器施加反向排序。

这是这两种方法的示例:

Java Collections reverseOrder()示例

Collections.sort(fruits, Collections.reverseOrder());
System.out.println(fruits);

它将以相反的字母顺序输出水果:

[Orange, Grape, Banana, Apple]

Java Collections reverseOrder(Comparator cmp)示例

Collections.sort(fruitList, Collections.reverseOrder(new SortByName()));
fruitList.forEach(fruit -> {
  System.out.println(fruit.getId() + " " + fruit.getName() + " " + 
    fruit.getTaste());
});

输出:

2 Orange Sour
3 Grape Sweet and Sour
4 Banana Sweet
1 Apple Sweet