Java Stream排序示例
在本教程中,我们将看到如何对列表进行排序 Stream.sorted()方法。
Java 8介绍了
Stream.sort()方法可以方便地对元素列表进行排序。
它有助于我们编写简短的函数样式代码而不是样板代码。 java.util.Stream有两个超载版本 sorted()方法。
sorted():返回具有自然秩序排序的元素的流sorted(Comparator<? super T> comparator):返回具有由提供的比较器排序的元素的流
如果使用Stream.sorted()方法然后可比较接口,由Integer类实现,将定义整数列表的自然顺序。
让我们了解我们如何使用 Stream.sorted()排序元素列表。
排序整数列表
我们可以简单地使用 sorted()对整数列表进行排序的方法。
List<Integer> result = listOfIntegers.stream() .sorted() .collect(Collectors.toList());
其中整数列表由Integer类实现的可比接口排序。
public final class Integer extends Number implements Comparable<Integer> {
....
/**
* Compares two {@code Integer} objects numerically.
*
* @param anotherInteger the {@code Integer} to be compared.
* @return the value {@code 0} if this {@code Integer} is
* equal to the argument {@code Integer}; a value less than
* {@code 0} if this {@code Integer} is numerically less
* than the argument {@code Integer}; and a value greater
* than {@code 0} if this {@code Integer} is numerically
* greater than the argument {@code Integer} (signed
* comparison).
* @since 1.2
*/
public int compareTo(Integer anotherInteger) {
return compare(this.value, anotherInteger.value);
}
/**
* Compares two {@code int} values numerically.
* The value returned is identical to what would be returned by:
*
* Integer.valueOf(x).compareTo(Integer.valueOf(y))
*
*
* @param x the first {@code int} to compare
* @param y the second {@code int} to compare
* @return the value {@code 0} if {@code x == y};
* a value less than {@code 0} if {@code x < y}; and
* a value greater than {@code 0} if {@code x > y}
* @since 1.7
*/
public static int compare(int x, int y) {
return (x < y) ? -1 : ((x == y) ? 0 : 1);
}
如我们所见,整数在此基础上进行了比较 (x < y) ? -1 : ((x == y) ? 0 : 1)逻辑。
你可以通过 Comparator.reverseOrder()排序方法以反转整数的排序列表。
List<Integer> reverseOrder = listOfIntegers.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList());
Comparator.reverseOrder()是静态方法,提供了一种对比较器,其强加自然排序。
让我们看看完整的例子来排序整数列表。
package org.igi.theitroad;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class SortListOfIntegers {
public static void main(String[] args) {
List<Integer> listOfIntegers = Arrays.asList(new Integer[] {40,34,21,37,20});
List<Integer> result = listOfIntegers.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(result);
List<Integer> reverseOrder = listOfIntegers.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
System.out.println(reverseOrder);
}
}
排序字符串列表
我们可以简单地使用 sorted()用于对字符串列表进行排序的方法。
List<String> result = listOfStrings.stream() .sorted() .collect(Collectors.toList());
其中字符串列表由字符串类实现的可比接口排序。
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
....
/**
* Compares two strings lexicographically.
*
* @param anotherString the {@code String} to be compared.
* @return the value {@code 0} if the argument string is equal to
* this string; a value less than {@code 0} if this string
* is lexicographically less than the string argument; and a
* value greater than {@code 0} if this string is
* lexicographically greater than the string argument.
*/
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
return len1 - len2;
}
如我们所见,整数在此基础上进行了比较 (x < y) ? -1 : ((x == y) ? 0 : 1)逻辑。
你可以通过 Comparator.reverseOrder()排序方法以反转整数的排序列表。
List<String> reverseOrder = listOfStrings.stream() .sorted(Comparator.reverseOrder()) .collect(Collectors.toList());
比较器.ReverseOrder()是静态方法,提供了一个对比较器强加自然排序的反向。
让我们看看完整的例子来排序整数列表。
package org.igi.theitroad;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class SortListOfStrings {
public static void main(String[] args) {
List<String> listOfLanguages = Arrays.asList(new String[] { "Python", "C++", "Java", "PHP" });
List<String> sortedListOfLanguages = listOfLanguages.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedListOfLanguages);
List<String> sortedListOfLanguagesRev = listOfLanguages.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
System.out.println(sortedListOfLanguagesRev);
}
}
输出:
[C++, Java, PHP, Python] [Python, PHP, Java, C++]
排序自定义对象列表
按自然秩序对学生列表进行排序
创建一个名为的类 Student.java
package org.igi.theitroad;
public class Student{
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
让我们使用Stream的Salted()来对学生的列表进行排序。
package org.igi.theitroad;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class SortListOfStudents {
public static void main(String[] args) {
List<Student> studentsList = getListOfStudents();
List<Student> sortedStudentsList= studentsList.stream()
.sorted()
.collect(Collectors.toList());
System.out.println(sortedStudentsList);
}
public static List<Student> getListOfStudents()
{
List<Student> studentList=new ArrayList<>();
Student s1=new Student("Peter",21);
Student s2=new Student("Harshal",18);
Student s3=new Student("Andy",17);
Student s4=new Student("Mary",20);
Student s5=new Student("Peter",19);
studentList.add(s1);
studentList.add(s2);
studentList.add(s3);
studentList.add(s4);
studentList.add(s5);
return studentList;
}
}
运行后报错:
Exception in thread “main" java.lang.ClassCastException: org.arpit.theitroad.Student cannot be cast to java.lang.Comparable at java.util.Comparators$NaturalOrderComparator.compare(Comparators.java:47) at java.util.TimSort.countRunAndMakeAscending(TimSort.java:355) at java.util.TimSort.sort(TimSort.java:220) at java.util.Arrays.sort(Arrays.java:1512) at java.util.stream.SortedOps$SizedRefSortingSink.end(SortedOps.java:353) at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:483) at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472) at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708) at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566) at org.arpit.theitroad.SortListOfStudents.main(SortListOfStudents.java:14)
你知道为什么我们在这里得到异常吗?
我们得到了 ClassCastException例外,因为我们没有实施 Comparable接口 Student类。
让我们实现类似的接口
Student类。
package org.igi.theitroad;
public class Student implements Comparable<Student>{
String name;
int age;
public Student(String name, int age) {
super();
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
@Override
public int compareTo(Student o) {
return this.getName().compareTo(o.getName());
}
}
学生列表将按学生名称排序。
按逆自然顺序排序学生列表
按下降订单按名称排序学生列表。
package org.igi.theitroad;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class SortListOfStudents {
public static void main(String[] args) {
List<Student> studentsList = getListOfStudents();
List<Student> sortedListOfStudent2 = listOfStudents.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
System.out.println(sortedStudentsList);
}
public static List<Student> getListOfStudents()
{
List<Student> studentList=new ArrayList<>();
Student s1=new Student("Peter",21);
Student s2=new Student("Harshal",18);
Student s3=new Student("Andy",17);
Student s4=new Student("Mary",20);
Student s5=new Student("Peter",19);
studentList.add(s1);
studentList.add(s2);
studentList.add(s3);
studentList.add(s4);
studentList.add(s5);
return studentList;
}
}
使用比较器按年龄排序学生列表
package org.igi.theitroad;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class SortListOfStudents {
public static void main(String[] args) {
List<Student> studentsList = getListOfStudents();
List<Student> studentsListByAge = studentsList.stream()
.sorted((s1,s2) -> s1.getAge()-s2.getAge())
.collect(Collectors.toList());
System.out.println(studentsListByAge);
}
public static List<Student> getListOfStudents()
{
List<Student> studentList=new ArrayList<>();
Student s1=new Student("Peter",21);
Student s2=new Student("Harshal",18);
Student s3=new Student("Andy",17);
Student s4=new Student("Mary",20);
Student s5=new Student("Peter",19);
studentList.add(s1);
studentList.add(s2);
studentList.add(s3);
studentList.add(s4);
studentList.add(s5);
return studentList;
}
}
你也可以使用 Comparator.comparing(Function<? super T, ? extends U> keyExtractor)根据年龄为基础进行排序。 Comparator.comparing()接受从类型映射排序键的函数,并返回由该排序键进行比较的比较器。
让我们说你想在年龄的基础上排序学生列表。
我们可以从学生对象中提取排序键年龄 Comparator.comparing()将返回一个比较器,它将排序该排序键。
Function<Student,Integer> fun = (s) -> s.getAge();
List<Student> studentsListByAge = studentsList.stream()
.sorted(Comparator.comparing(fun))
.collect(Collectors.toList());
这里 Comparator.comparing()返回基于年龄的新比较器进行排序。
我们还可以在此处使用方法引用,因为我们只是在调用s。
GetAge()在函数接口中。
Function<Student,Integer> fun = Student::getAge
List<Student> studentsListByAge = studentsList.stream()
.sorted(Comparator.comparing(fun))
.collect(Collectors.toList());
假设我们想根据年龄按降序排序学生列表。
我们可以传递另一个比较器 Comparator.comparing()基于排序键进行自定义排序。
List<Student> sortedListOfStudent5 = listOfStudents.stream() .sorted(Comparator.comparing(Student::getAge,(age1,age2) -> age2 - age1)) .collect(Collectors.toList());
其中比较器.paring()有两个参数。 Student::getAge定义排序键。 (age1,age2) -> age2 - age1)根据排序密钥定义自定义排序。
这是完整的例子。
package org.igi.theitroad;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public class SortListOfStudents {
public static void main(String[] args) {
List<Student> sList = getListOfStudents();
Function<Student,Integer> fun = (s) -> s.getAge();
List<Student> sListByAge = sList.stream()
.sorted(Comparator.comparing(fun))
.collect(Collectors.toList());
System.out.println("Sorted list by age ascending: "+sListByAge);
List<Student> sListByAgeRev = sList.stream()
.sorted(Comparator.comparing(Student::getAge
,(age1,age2) -> age2 - age1))
.collect(Collectors.toList());
System.out.println("Sorted list by age descending: "+sListByAgeRev);
}
public static List<Student> getListOfStudents()
{
List<Student> studentList=new ArrayList<>();
Student s1=new Student("Peter",21);
Student s2=new Student("Harshal",18);
Student s3=new Student("Andy",17);
Student s4=new Student("Mary",20);
Student s5=new Student("Peter",19);
studentList.add(s1);
studentList.add(s2);
studentList.add(s3);
studentList.add(s4);
studentList.add(s5);
return studentList;
}
}
按名称和年龄排序学生列表
假设我们想按名称列出学生,如果姓名是相同的,那么我们需要按年龄排序。
我们可以使用Comparator.ThenComparing()使用Comparator.comparing()来实现相同的。
让我们在举例的帮助下看看。
package org.igi.theitroad;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class SortListOfStudents {
public static void main(String[] args) {
List<Student> sList = getListOfStudents();
List<Student> sListByNameAge = sList.stream()
.sorted(Comparator.comparing(Student::getName)
.thenComparing(Student::getAge))
.collect(Collectors.toList());
System.out.println(sListByNameAge);
}
public static List<Student> getListOfStudents()
{
List<Student> studentList=new ArrayList<>();
Student s1=new Student("Peter",21);
Student s2=new Student("Harshal",18);
Student s3=new Student("Andy",17);
Student s4=new Student("Mary",20);
Student s5=new Student("Peter",19);
studentList.add(s1);
studentList.add(s2);
studentList.add(s3);
studentList.add(s4);
studentList.add(s5);
return studentList;
}
}
正如你所看到的,有两个学生命名 Peter在列表中,按年龄排序。

