前沿:在美团已经实习了一段时间,在看业务代码的时候,有一些我不熟悉的语法操作,百度了一下,这些简便的写法其实是语法糖。
- 语法糖:语法糖就是一种便捷写法
- 注:下面的只是我自己想当然认为它们是语法糖
1、::
双冒号操作符
1.1 使用方式
:: 是是JDK8的一种语法糖,根据不同的使用情景,其使用方式为以下的四种情景:
- 实例对象::实例方法
- 该方式的一个典型用法就是
x -> System.out.println(x)
可以替换成System.out::println
- 在
System类
中有一个静态成员对象out
,其是printStream类
的实例(即在System类中为public static final printStream out ,且out是static的),因此,System.out是printStream的实例化对象,System.out 表示屏幕输出,这时候还只是字节流而已,当调用printStream的方法println()是就表示用什么用的方式打印输出的关系了。- 原本应该写为:
.forEach(element -> {System.out.println(element)})
但是System.out.println的参数和传递的参数element 的类型完全匹配,所以这样的时候就可以简化为:.forEach(System.out::println)
- 类名::实例方法
- 类名::静态方法
- 类名::new
当创建对象
() -> new ArrayList<>()
时,可以替换为ArrayList::new
,因为 new关键字实际上调用的是ArrayList的构造方法
Class 是类名,产生于class Class { }。object 是实例对象,产生于 Class object = new Class() |
在使用的过程中要注意以下几点,
- 方法后面并没有()
- 懒加载方法是否调用要看调用方使用情况
1.2 举例
package org.example;
import java.util.Arrays;
import java.util.List;
import java.util.function.*;
public class Sugar {
private int paoPaoTang = 0;
private int aErBeiSi = 1;
/**
* 下面的两个方法分别是:无返回值的实例方法、有返回值的实例方法
* @param a
* @param s
*/
public void noValueInstance(int a, String s){
int b = Integer.valueOf(s).intValue();
int sum = a +b + paoPaoTang +aErBeiSi;
System.out.println(String.format("我没有返回值,我输出的值是:%d", sum));
}
public int hasValueInstance(int a, String s){
int b = Integer.valueOf(s).intValue();
int sum = a + b +paoPaoTang + aErBeiSi;
System.out.println("我有返回值");
return sum;
}
/**
* 下面的两个方法分别是:无返回值的静态方法、有返回值的静态方法
* @param choice
*/
public static void noValueStatic(int choice){
if(choice==0){
System.out.println("我是泡泡糖");
}else{
System.out.println("我是阿尔卑斯");
}
}
public static int hasValueStatic(int choice){
Sugar sugar = new Sugar();
if(choice==0){
return sugar.paoPaoTang;
}else{
return sugar.aErBeiSi;
}
}
public static void printValur(String str) {
System.out.println("print value : " + str);
}
public static void main(String[] args) {
List<String> al = Arrays.asList("a", "b", "c", "d");
al.forEach(Sugar::printValur);
// 下面的方法和上面等价的
Consumer<String> methodParam = Sugar::printValur;
al.forEach(x -> methodParam.accept(x));
System.out.println("*************************************************");
int a = 1;
String s = "2";
Sugar sugar = new Sugar();
/**
* 无返回值的实例方法
* 请注意:BiConsumer无返回值,它接受两个参数作为参数。
*/
BiConsumer<Integer, String> noValueInstance = sugar::noValueInstance;
noValueInstance.accept(a, s);
/**
* 有返回值的实例方法。
* 请注意:BiFunction接受两个参数并返回一个值。在声明BiFunction时,我们需要告诉我们将传递什么类型的参数以及什么是返回类型。
*/
// 方式一
ToIntBiFunction<Integer, String> hasValueInstance = sugar::hasValueInstance;
int result = hasValueInstance.applyAsInt(a, s);
System.out.println(result);
// 方式二
BiFunction<Integer, String, Integer> hasValueInstance1 = sugar::hasValueInstance;
int result1 = hasValueInstance1.apply(a, s);
System.out.println(result1);
System.out.println("*************************************************");
/**
* 无返回值的静态方法
*
* Consumer的作用就是定义一个函数,然后对其进行消费处理,(accept方法),其接受一个参数,但无返回值
*/
Consumer<Integer> noValueStatic = Sugar::noValueStatic;
noValueStatic.accept(0);
IntConsumer noValueStatic1 = Sugar::noValueStatic;
noValueStatic1.accept(1);
/**
* 有返回值的静态方法
*
* Function的作用就是定义一个函数,其功能方法是apply,其接受一个参数,有返回值
*/
Function<Integer, Integer> hasValueStatic = Sugar::hasValueStatic;
int res = hasValueStatic.apply(0);
System.out.println(res);
IntFunction<Integer> hasValueStatic1 = Sugar::hasValueStatic;
int res1 = hasValueStatic.apply(1);
System.out.println(res1);
}
}
Consumer与Function参考本篇文章
参考:https://blog.csdn.net/qq_27389705/article/details/89083963
参考:https://www.cnblogs.com/yanlong300/p/9209243.html
2、->
2.1 Java 8 函数式接口
2.1.1 函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口
,函数式接口可以被隐式转换为 lambda 表达式。如定义了一个函数式接口如下:
@FunctionalInterface
interface GreetingService
{
void sayMessage(String message);
}
那么就可以使用Lambda表达式来表示该接口的一个实现 (注:JAVA 8 之前一般是用匿名类实现的):
GreetingService greetService1 = message -> System.out.println("Hello " + message);
函数式接口可以对现有的函数友好地支持 lambda
。
2.1.2 函数式接口实例
Predicate <T> 接口是一个函数式接口,它接受一个输入参数 T,返回一个布尔值结果
。该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非),该接口用于测试对象是 true 或 false。我们可以通过以下实例(Java8Tester.java)来了解函数式接口 Predicate 的使用:
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class Java8Tester {
public static void main(String args[]){
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
// Predicate<Integer> predicate = n -> true
// n 是一个参数传递到 Predicate 接口的 test 方法
// n 如果存在则 test 方法返回 true
System.out.println("输出所有数据:");
// 传递参数 n
eval(list, n->true);
// Predicate<Integer> predicate1 = n -> n%2 == 0
// n 是一个参数传递到 Predicate 接口的 test 方法
// 如果 n%2 为 0 test 方法返回 true
System.out.println("输出所有偶数:");
eval(list, n-> n%2 == 0 );
// Predicate<Integer> predicate2 = n -> n > 3
// n 是一个参数传递到 Predicate 接口的 test 方法
// 如果 n 大于 3 test 方法返回 true
System.out.println("输出大于 3 的所有数字:");
eval(list, n-> n > 3 );
}
public static void eval(List<Integer> list, Predicate<Integer> predicate) {
for(Integer n: list) {
if(predicate.test(n)) {
System.out.println(n + " ");
}
}
}
}
执行以上结果:
$ javac Java8Tester.java
$ java Java8Tester
输出所有数据:
1
2
3
4
5
6
7
8
9
输出所有偶数:
2
4
6
8
输出大于 3 的所有数字:
4
5
6
7
8
9
interface Person{
void say(String t);
}
class AnimalSay{
public static void saySomething(String something,Person person) {
person.say(something);
}
}
public class Mian {
public static void main(String[] args) {
Person xiaoMing = (x) -> { System.out.println(x); };
//xiaoMing.say("hello"); //1
AnimalSay.saySomething("hello", xiaoMing ); //2
// 可以直接把 lambda 表达式直接放在需要的位置。这时候 lambda 就可以自动变成所需类
//AnimalSay.saySomething("hello", (x)->{System.out.println(x)};); //3
}
}
2.1.3 链接
2.2 Java Lambda 表达式
2.2.1 特性
Lambda 表达式,也可称为闭包
,它是推动 Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)
,使用 Lambda 表达式可以使代码变的更加简洁紧凑。- Labmda表达式一般用来实现一个函数式接口,省去了之前需要专为他编写一个实现类或者匿名内部类的代码,直接对接口进行实现。因为该接口中只有一个抽象方法,因此不会有冲突的可能。
2.2.2 语法
lambda 表达式的语法格式如下:
(parameters) -> expression
或
(parameters) ->{ statements; }
以下是lambda表达式的重要特征:
可选类型声明
:不需要声明参数类型,编译器可以统一识别参数值。可选的参数圆括号
:一个参数无需定义圆括号,但多个参数需要定义圆括号。可选的大括号
:如果主体包含了一个语句,就不需要使用大括号。可选的返回关键字
:如果主体只有一个表达式返回值则编译器会自动返回值;若有多个语句,大括号需要指明表达式返回了一个数值。
// 1. 不需要参数,返回值为 5
() -> 5
// 2. 接收一个参数(数字类型),返回其2倍的值
x -> 2 * x
// 3. 接受2个参数(数字),并返回他们的差值
(x, y) -> x – y
// 4. 接收2个int型整数,返回他们的和
(int x, int y) -> x + y
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)
(String s) -> System.out.print(s)
2.2.3 举例
public class Java8Tester {
public static void main(String args[]){
Java8Tester tester = new Java8Tester();
// 类型声明
MathOperation addition = (int a, int b) -> a + b;
// 不用类型声明
MathOperation subtraction = (a, b) -> a - b;
// 大括号中的返回语句
MathOperation multiplication = (int a, int b) -> { return a * b; };
// 没有大括号及返回语句
MathOperation division = (int a, int b) -> a / b;
System.out.println("10 + 5 = " + tester.operate(10, 5, addition));
System.out.println("10 - 5 = " + tester.operate(10, 5, subtraction));
System.out.println("10 x 5 = " + tester.operate(10, 5, multiplication));
System.out.println("10 / 5 = " + tester.operate(10, 5, division));
// 不用括号
GreetingService greetService1 = message ->
System.out.println("Hello " + message);
// 用括号
GreetingService greetService2 = (message) ->
System.out.println("Hello " + message);
greetService1.sayMessage("Runoob");
greetService2.sayMessage("Google");
}
interface MathOperation {
int operation(int a, int b);
}
private int operate(int a, int b, MathOperation mathOperation){
return mathOperation.operation(a, b);
}
interface GreetingService {
void sayMessage(String message);
}
}
执行以上脚本,输出结果为:
```java
$ javac Java8Tester.java
$ java Java8Tester
10 + 5 = 15
10 - 5 = 5
10 x 5 = 50
10 / 5 = 2
Hello Runoob
Hello Google
使用 Lambda 表达式需要注意以下两点:
- Lambda 表达式用于
只有一个匿名方法的函数式接口
,主要用来定义行内执行的方法类型接口
,例如,一个简单方法接口。在上面例子中,我们使用各种类型的Lambda表达式来定义MathOperation接口的方法。然后我们定义了sayMessage的执行。 Lambda 表达式免去了使用匿名方法的麻烦
,并且给予Java简单但是强大的函数化的编程能力。
在这里插一个多线程的lambda表达式使用技巧:
链接:https://www.zhihu.com/question/302776698/answer/1522159326
public class SynchronizedTest {
public synchronized void method1() {
System.out.println("Method 1 start");
try {
System.out.println("Method 1 execute");
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method 1 end");
}
public synchronized void method2() {
System.out.println("Method 2 start");
try {
System.out.println("Method 2 execute");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method 2 end");
}
public static void main(String[] args) {
// 一种最简洁的启动方法
//new Thread( ()-> new SynchronizedTest().method1() ).start();
//新建实例对象的启动方法
final SynchronizedTest test = new SynchronizedTest();
new Thread(test::method1).start();
new Thread( ()-> test.method1() ).start();
//显式的赋值Runnable后再启动
Runnable tt = test::method1;
new Thread(tt).start();
new Thread(test::method2).start();
}
}
//运行完后对结果有没有疑问? 为什么2后面还有1?
Method 1 start
Method 1 execute
Method 1 end
Method 2 start
Method 2 execute
Method 2 end
Method 1 start
Method 1 execute
Method 1 end
Method 1 start
Method 1 execute
Method 1 end
2.2.4 变量作用域
lambda 表达式只能引用标记了 final 的外层局部变量,这就是说不能在 lambda 内部修改定义在域外的局部变量,否则会编译错误。
2.2.5 链接
2.3 与foreach()
搭配更美味
Java8 推出的lambda表达式,与一众的 =>
不同,Java选择了 ->
做为箭头符号,lambda表达式的基本格式是这样的:
( )->{ }
具体是什么意思呢,这里就要提一下使用lambda表达式的前提了,labmda表达式一般用来实现一个函数式接口
,比如java.lang.Iterable 的 foreach(xxx
)方法中的xxx
位置需要一个 Consumer 接口类,
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
而 Consumer 正好是一个函数式接口(@FunctionalInterface 注解
了解一下)。
@FunctionalInterface
public interface Consumer<T> {
...
void accept(T t);
...
}
这时候可以这么用lamda表达式来实现一个函数式接口,即 Consumer one = (x) -> { System.out.println(x) }
,然后再把 one
传进去forEach
就可以,与上面的代码结合起来看,x
就是accept
中的t
,花括号里没有return
是因为accept
返回值是void
(因为 Consumer 接口中只有一个方法,因此不会有冲突的可能
)。
//第一种
Consumer one = (x) -> { System.out.println(x);};
Iterable.foreach(one);
//第二种
Iterable.foreach( x->System.out.println(x) );
3 Foreach
3.1 特性
foreach语句是for语句的特殊简化版本,提高了代码的可读性和安全性(不用怕数组越界)
,但是foreach语句并不能完全取代for语句(在用到对集合或者数组索引的情况下,foreach显得力不从心,这个时候是用for语句的时候了),然而,任何的foreach语句都可以改写为for语句版本。- foreach一般结合泛型使用
- foreach并不是一个关键字,习惯上将这种特殊的for语句格式称之为
“foreach”语句
3.2 语句格式:
for(元素类型t 元素变量x : 遍历对象obj){
引用了x的java语句;
}
3.3
-
特别地,一个经常见到的例子是:
原本应该写为:.forEach(element -> {System.out.println(element)}),但是System.out.println的参数和传递的参数element 的类型完全匹配,所以这样的时候就可以简化为:.forEach(System.out::println)
-
list.forEach((t) -> System.out.println(t))
,如果还不明白的话,也可以这样,list.forEach((String t) -> System.out.println(t));
3.4 举例
3.4.1
package org.example;
import java.util.ArrayList;
import java.util.List;
public class Foreach {
// https://www.zhihu.com/question/302776698/answer/1522159326
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("a");
list.add("b");
list.add("c");
list.forEach(System.out::println);
list.forEach((t)->System.out.println(t));
list.forEach((String t)->System.out.println(t));
}
}
a
b
c
a
b
c
a
b
c
3.4.2
public class TestArray {
/**
* 集合转换为一维数组
*/
public void listToArray() {
//创建List并添加元素
List<String> list = new ArrayList<String>();
list.add("1");
list.add("3");
list.add("4");
//利用froeach语句输出集合元素
System.out.println("----2----froeach语句输出集合元素");
for (String x : list) {
System.out.println(x);
}
//将ArrayList转换为数组
Object s[] = list.toArray();
//利用foreach语句输出集合元素
System.out.println("----2----froeach语句输出集合转换而来的数组元素");
for (Object x : s) {
System.out.println(x.toString()); //逐个输出数组元素的值
}
}
public static void main(String args[]) {
TestArray test = new TestArray();
test.listToArray();
}
}
参考:https://www.cnblogs.com/elleniou/archive/2012/04/27/2473050.html
4、list.stream().map().collect(Collectors.toList())
4.1.0 问题来源
userList
:User实体类对象集合
User
:实体类
getId
:实体类属性的方法
- List ids= userList.stream().map(User::getId).collect(Collectors.toList())
- 或者 把数据放到map根据
user.getId(条件)
,再转换成list- List ids= userList.stream().map(user->user.getId()).collect(Collectors.toList());
4.1 函数说明
4.1.1 stream()
stream()
把一个源数据(可以是集合,数组,I/O channel, 产生器generator 等)转化成流Java8提供了Stream(流)处理集合,它可以对集合进行操作
,可以执行非常复杂的查找、过滤和映射数据等操作- Stream API 借助于同样新出现的Lambda表达式,极大的提高编程效率和程序可读性
创建UserService.class(用户信息业务逻辑类)
:
import com.pjb.streamdemo.entity.User;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
* 用户信息业务逻辑类
* @author pan_junbiao
**/
public class UserService
{
/**
* 获取用户列表
*/
public static List<User> getUserList()
{
List<User> userList = new ArrayList<User>();
userList.add(new User(1, "pan_junbiao的博客_01", "男", 32, "研发部", BigDecimal.valueOf(1600)));
userList.add(new User(2, "pan_junbiao的博客_02", "男", 30, "财务部", BigDecimal.valueOf(1800)));
userList.add(new User(3, "pan_junbiao的博客_03", "女", 20, "人事部", BigDecimal.valueOf(1700)));
userList.add(new User(4, "pan_junbiao的博客_04", "男", 38, "研发部", BigDecimal.valueOf(1500)));
userList.add(new User(5, "pan_junbiao的博客_05", "女", 25, "财务部", BigDecimal.valueOf(1200)));
return userList;
}
}
4.1.2 forEach()
forEach()迭代流中的每个数据
例子1
:
/**
* 使用forEach()遍历列表信息
* @author pan_junbiao
*/
@Test
public void forEachTest()
{
//获取用户列表
List<User> userList = UserService.getUserList();
//遍历用户列表
userList.forEach(System.out::println);
}
上述遍历语句等同于以下语句:
userList.forEach(user -> {System.out.println(user);});
例子2
,以下代码片段使用 forEach() 输出了10个随机数。
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
4.1.3 filter(T -> boolean)
filter()方法通过设置的条件过滤列表数据
例子1
,获取部门为“研发部”的用户列表。
/**
* 使用filter()过滤列表信息
* @author pan_junbiao
*/
@Test
public void filterTest()
{
//获取用户列表
List<User> userList = UserService.getUserList();
//获取部门为“研发部”的用户列表
userList = userList.stream().filter(user -> user.getDepartment() == "研发部").collect(Collectors.toList());
//遍历用户列表
userList.forEach(System.out::println);
}
例子2
,以下代码片段使用 filter 方法过滤出空字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
int count = strings.stream().filter(string -> string.isEmpty()).count();
// parallelStream 是流并行处理方法,我们可以很容易的在顺序运行和并行直接切换。使用 parallelStream 来输出空字符串的数量:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
// 获取空字符串的数量
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();
4.1.4 findAny() 和 findFirst()
- 使用 findAny() 和 findFirst() 获取第一条数据。
例子1
,获取用户名称为“pan_junbiao的博客_02”的用户信息,如果未找到则返回null。
/**
* 使用findAny()获取第一条数据
* @author pan_junbiao
*/
@Test
public void findAnytTest()
{
//获取用户列表
List<User> userList = UserService.getUserList();
//获取用户名称为“pan_junbiao的博客_02”的用户信息,如果没有找到则返回null
User user = userList.stream().filter(u -> u.getName().equals("pan_junbiao的博客_02")).findAny().orElse(null);
//打印用户信息
System.out.println(user);
}
注意:findFirst() 和 findAny() 都是获取列表中的第一条数据,但是findAny()操作,返回的元素是不确定的,对于同一个列表多次调用findAny()有可能会返回不同的值。使用findAny()是为了更高效的性能。如果是数据较少,串行地情况下,一般会返回第一个结果,如果是并行(parallelStream并行流)的情况,那就不能确保是第一个。
例如:使用parallelStream并行流(parallelStream方法能生成并行流
),findAny() 返回的就不一定是第一条数据。
User user = userList.parallelStream().filter(u -> u.getName().startsWith("p")).findAny().orElse(null);
4.1.5 map(T -> R) 和 flatMap(T -> Stream)
- 使用 map() 将流中的每一个元素 T 映射为 R(
映射每个元素得到对应的结果
) - 使用 flatMap() 将流中的每一个元素 T 映射为一个流,再把每一个流连接成为一个流。
例子1
,使用 map() 方法获取用户列表中的名称列。
/**
* 使用map()获取列元素
* @author pan_junbiao
*/
@Test
public void mapTest()
{
//获取用户列表
List<User> userList = UserService.getUserList();
//获取用户名称列表
List<String> nameList = userList.stream().map(User::getName).collect(Collectors.toList());
//或者:List<String> nameList = userList.stream().map(user -> user.getName()).collect(Collectors.toList());
//遍历名称列表
nameList.forEach(System.out::println);
}
若不想要返回List列表
,想要的返回的结果为数组类型
,写法如下:
//数组类型
String[] nameArray = userList.stream().map(User::getName).collect(Collectors.toList()).toArray(new String[userList.size()]);
例子2
,以下代码片段使用 map 输出了元素对应的平方数:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
// 获取对应的平方数
List<Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
例子3
,使用 flatMap() 将流中的每一个元素连接成为一个流。
/**
* 使用flatMap()将流中的每一个元素连接成为一个流
* @author pan_junbiao
*/
@Test
public void flatMapTest()
{
//创建城市
List<String> cityList = new ArrayList<String>();
cityList.add("北京;上海;深圳;");
cityList.add("广州;武汉;杭州;");
//分隔城市列表,使用 flatMap() 将流中的每一个元素连接成为一个流。
cityList = cityList.stream()
.map(city -> city.split(";"))
.flatMap(Arrays::stream)
.collect(Collectors.toList());
//遍历城市列表
cityList.forEach(System.out::println);
}
4.1.6 distinct()
- 使用 distinct() 方法可以去除重复的数据。
例子1
,获取部门列表,并去除重复数据。
/**
* 使用distinct()去除重复数据
* @author pan_junbiao
*/
@Test
public void distinctTest()
{
//获取用户列表
List<User> userList = UserService.getUserList();
//获取部门列表,并去除重复数据
List<String> departmentList = userList.stream().map(User::getDepartment).distinct().collect(Collectors.toList());
//遍历部门列表
departmentList.forEach(System.out::println);
}
4.1.7 limit(long n) 和 skip(long n)
- limit(long n) 方法用于返回前n条数据,skip(long n) 方法用于跳过前n条数据
例子1
,获取用户列表,要求跳过第1条数据后的前3条数据。
/**
* limit(long n)方法用于返回前n条数据
* skip(long n)方法用于跳过前n条数据
* @author pan_junbiao
*/
@Test
public void limitAndSkipTest()
{
//获取用户列表
List<User> userList = UserService.getUserList();
//获取用户列表,要求跳过第1条数据后的前3条数据
userList = userList.stream()
.skip(1)
.limit(3)
.collect(Collectors.toList());
//遍历用户列表
userList.forEach(System.out::println);
}
例子2
, 以下代码片段使用 limit 方法打印出 10 条数据:
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
4.1.8 sorted() / sorted((T, T) -> int)
- 如果流中的元素的类实现了 Comparable 接口,即有自己的排序规则,那么可以直接调用 sorted() 方法对元素进行排序,如 Stream。反之, 需要调用 sorted((T, T) -> int) 实现 Comparator 接口。
- 例子1,根据用户年龄进行排序。
/**
* 使用 sorted() 排序
* @author pan_junbiao
*/
@Test
public void sortedTest()
{
//获取用户列表
List<User> userList = UserService.getUserList();
//根据年龄排序(升序)
userList = userList.stream().sorted((u1, u2) -> u1.getAge() - u2.getAge()).collect(Collectors.toList());
//推荐:userList = userList.stream().sorted(Comparator.comparingInt(User::getAge)).collect(Collectors.toList());
//降序:userList = userList.stream().sorted(Comparator.comparingInt(User::getAge).reversed()).collect(Collectors.toList());
//遍历用户列表
userList.forEach(System.out::println);
}
例子2
,以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
4.1.9 Collectors()
- Collectors()类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
List<String>strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
System.out.println("筛选列表: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("合并字符串: " + mergedString);
4.2 参考链接
5、Enum类
https://blog.csdn.net/javazejian/article/details/71333103
https://blog.csdn.net/qq_27093465/article/details/52180865