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
在列表中,按年龄排序。