Lambda表达式是JDK8的一个新特性,可以取代大部分的匿名内部类,写出更优雅的Java代码,尤其在集合的遍历和其他集合操作中,可以极大的优化代码结构。
JDK也提供了大量的内置函数式接口供我们使用,使得Lambda表达式的运用更加方便、高效。
虽然使用Lambda表达式可以对某些接口进行简单的实现,但并不是所有接口都可以使用Lambda表达式来实现。Lambda规定接口中只能有一个需要被实现的方法,不是规定接口中只能有一个方法。
JDK8中有另一个新特性:default,被default修饰的方法会有默认实现,不是必须被实现的方法,所以不影响Lambda表达式的使用。
修饰函数式接口的,要求接口中的抽象方法只有一个。这个注解往往会和Lambda表达式一起出现。
作用:
验证当前接口是否只有一个需要被实现的方法,如果不满足就编译报错。
package com.wind.lambda;
/**
* Lambda表达式 基础语法测试
*
* @author Wind
*/
public class LambdaTest01 {
public static void main(String[] args) {
/*
以前的写法 使用匿名内部类
*/
NoRetrunNoParam noRetrunNoParam = new NoRetrunNoParam() {
@Override
public void method() {
System.out.println("匿名内部类 OK!");
}
};
noRetrunNoParam.method();
/*
无返回值无参数
*/
NoRetrunNoParam noRetrunNoParam1 = () -> {
System.out.println("无返回值无参数~OK!");
};
noRetrunNoParam1.method();
/*
无返回值有一个参数
*/
NoRetrunOneParam noRetrunOneParam = (int a) -> {
System.out.println("无返回值有一个参数:" + a);
};
noRetrunOneParam.method(10);
/*
无返回值有多个参数
*/
NoRetrunMultiParam noRetrunMultiParam = (int a, int b) -> {
System.out.println("无返回值有多个参数:" + (a + b));
};
noRetrunMultiParam.method(10, 5);
/*
有返回值无参数
*/
RetrunNoParam retrunNoParam = () -> {
return 110;
};
System.out.println("有返回值无参数:" + retrunNoParam.method());
/*
有返回值有一个参数
*/
RetrunOneParam retrunOneParam = (int a) -> {
return a;
};
System.out.println("有返回值有一个参数:" + retrunOneParam.method(120));
/*
有返回值有多个参数
*/
RetrunMultiParam retrunMultiParam = (int a, int b) -> {
return a + b;
};
System.out.println("有返回值有多个参数:" + retrunMultiParam.method(20, 30));
}
}
package com.wind.lambda;
/**
* Lambda表达式 语法简化
*
* 简化主要针对的是:参数类型、小括号、大括号
*
* @author Wind
*/
public class LambdaTest02 {
public static void main(String[] args) {
/*
1. 简化参数类型:可以不写参数类型,但必须所有参数都不写
*/
// 正常语法
NoRetrunMultiParam noRetrunMultiParam = (int a, int b) -> {
System.out.println("无返回值有多个参数:" + (a + b));
};
noRetrunMultiParam.method(10, 5);
// 简化写法:可以不写参数类型,但必须所有参数都不写
NoRetrunMultiParam noRetrunMultiParam1 = (a, b) -> {
System.out.println(a + b);
};
noRetrunMultiParam1.method(15, 20);
/*
2. 简化参数小括号。如果只有一个参数可以省略参数小括号()
*/
// 正常语法
NoRetrunOneParam noRetrunOneParam = (int a) -> {
System.out.println("无返回值有一个参数:" + a);
};
noRetrunOneParam.method(10);
// 简化写法:如果只有一个参数可以省略参数小括号()
NoRetrunOneParam noRetrunOneParam1 = a -> {
System.out.println("只有一个参数可以省略参数小括号()" + a);
};
noRetrunOneParam1.method(10);
/*
3. 简化方法体大括号。如果方法体中只有一行语句,则可以省略方法体大括号{}
*/
// 正常语法
NoRetrunNoParam noRetrunNoParam1 = () -> {
System.out.println("无返回值无参数~OK!");
};
noRetrunNoParam1.method();
// 简化写法:方法体中只有一行语句,则可以省略方法体大括号{}
NoRetrunNoParam noRetrunNoParam2 = () -> System.out.println("当实现类方法体中只有一行代码可以省略大括号~OK!");
noRetrunNoParam2.method();
/*
4. 简化方法体大括号。如果方法体只有一条语句,并且是 return 语句,则可省略方法体大括号和 return 关键字
*/
// 正常语法
RetrunMultiParam retrunMultiParam = (int a, int b) -> {
return a + b;
};
System.out.println("有返回值有多个参数:" + retrunMultiParam.method(20, 30));
// 简化语法
RetrunMultiParam retrunMultiParam1 = (a, b) -> a + b;
System.out.println("有返回值有多个参数:" + retrunMultiParam1.method(20, 30));
}
}
有时候我们不是必须要自己重写某个匿名内部类的方法,我们可以利用Lambda表达式快速指向一个已经被实现的方法。
语法:方法归属者 :: 方法名
静态方法的归属者为类名
接口 对象名 = 类名::静态方法名;
普通方法归属者为对象
对象 对象名 = new 对象();
接口 接口对象 = 对象名::成员方法名;
package com.wind.lambda;
/**
* Lambda表达式引用方法
*
* @author Wind
*/
public class LambdaTest03 {
public static void main(String[] args) {
// Lambda表达式引用已经实现的静态方法
RetrunOneParam retrunOneParam = LambdaTest03::numStatic;
System.out.println(retrunOneParam.method(20));
// Lambda表达式引用已经实现的普通方法
LambdaTest03 lambdaTest03 = new LambdaTest03();
RetrunOneParam retrunOneParam1 = lambdaTest03::numGeneral;
System.out.println(retrunOneParam1.method(50));
}
/**
* 静态方法
*
* @param a
* @return
*/
public static int numStatic(int a) {
return a + 1000;
}
/**
* 普通方法
*
* @param a
* @return
*/
public int numGeneral(int a) {
return a + 1500;
}
}
一般我们需要声明接口,改接口作为对象的生成器,通过 类名::new
的方式来实例化对象,然后调用方法返回对象。
package com.wind.lambda;
/**
* Lambda表达式 构造方法的引用
*
* @author Wind
*/
public class LambdaTest04 {
public static void main(String[] args) {
// 使用无参构造器来引用 1
ItemCreatorBlackConstruct construct1 = () -> new Item();
Item item1 = construct1.getItem();
// 使用无参构造器来引用 2
ItemCreatorBlackConstruct construct2 = Item::new;
Item item2 = construct2.getItem();
// 有参的构造方法
ItemCreatorParamContruct contruct3 = Item::new;
Item item3 = contruct3.getItem(1, "张三", 12.3);
}
}
@FunctionalInterface
interface ItemCreatorBlackConstruct {
Item getItem();
}
@FunctionalInterface
interface ItemCreatorParamContruct {
Item getItem(int id, String name, double price);
}
class Item {
int id;
String name;
double price;
public Item() {
}
public Item(int id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
}
我们以往都是通过创建 Thread 对象,然后通过匿名内部类重写 run() 方法。一提到匿名内部类 我们就应该想到可以使用 Lambda 表达式来简化线程创建过程。
package com.wind.lambda;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static java.util.concurrent.Executors.*;
/**
* Lambda表达式 创建线程对象
*
* @author Wind
*/
public class LambdaTest05 {
public static void main(String[] args) {
/*
Runable
*/
// 以前写法
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("OK~!");
}
}).start();
// Lambda表达式创建
new Thread(() -> {
System.out.println("OK~!");
}).start();
// 简化上面Lambda
new Thread(() -> System.out.println("OK~!")).start();
/*
提交
*/
ExecutorService executorService = newCachedThreadPool();
// Runable(无返回值)
executorService.submit(() -> {
System.out.println("OK~!");
});
// Callable(有返回值)
executorService.submit(() -> {
return "完成了!";
});
}
}
package com.wind.lambda;
import java.util.Arrays;
import java.util.List;
/**
* Lambda表达式 遍历集合
*
* @author Wind
*/
public class LambdaTest06 {
public static void main(String[] args) {
// Arrays工具类创建集合
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
// 普通for循环遍历集合
for (int i = 0; i < list.size(); i++) {
System.out.print(list.get(i) + "\t");
}
System.out.println();
System.out.println("-------------------------------------------------------");
// 增强for循环遍历集合
for (Integer i : list) {
System.out.print(i + "\t");
}
System.out.println();
System.out.println("-------------------------------------------------------");
/*
使用Lambda表达式遍历
*/
list.forEach((t) -> {
System.out.print(t + "\t");
});
System.out.println();
System.out.println("-------------------------------------------------------");
// 简化
list.forEach(t -> System.out.print(t + "\t"));
System.out.println();
System.out.println("-------------------------------------------------------");
// 极简
list.forEach(System.out::print);
}
}
package com.wind.lambda;
import java.util.ArrayList;
import java.util.List;
/**
* Lambda表达式 遍历集合
*
* @author Wind
*/
public class LambdaTest07 {
public static void main(String[] args) {
List<Star> stars = new ArrayList<>();
stars.add(new Star(1, "刘德华", true));
stars.add(new Star(2, "郭富城", true));
stars.add(new Star(3, "迪丽热巴", false));
stars.add(new Star(4, "水菜麗", false));
stars.add(new Star(5, "泷泽萝拉", false));
// 普通for循环移除元素
for (int i = 0; i < stars.size(); i++) {
if (stars.get(i).getId() == 1) {
stars.remove(stars.get(i));
break;
}
}
System.out.println(stars);
System.out.println("----------------------------------");
// 增强for循环 移除元素
for (Star star : stars) {
if (star.getId() == 2) {
stars.remove(star);
break;
}
}
System.out.println(stars);
System.out.println("----------------------------------");
/*
Lambda 表达式移除集合元素
*/
stars.removeIf((t) -> {
return t.getId() == 3;
});
System.out.println(stars);
System.out.println("----------------------------------");
// 简化
stars.removeIf(t -> t.getId() == 5);
System.out.println(stars);
System.out.println("----------------------------------");
}
}
package com.wind.lambda;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
/**
* Lambda表达式 遍历集合
*
* @author Wind
*/
public class LambdaTest08 {
public static void main(String[] args) {
List<Star> stars = new ArrayList<>();
stars.add(new Star(4, "刘德华", true));
stars.add(new Star(3, "郭富城", true));
stars.add(new Star(2, "迪丽热巴", false));
stars.add(new Star(5, "水菜麗", false));
stars.add(new Star(1, "泷泽萝拉", false));
// 使用集合工具类,给集合升序排序
Collections.sort(stars, new Comparator<Star>() {
@Override
public int compare(Star o1, Star o2) {
return o1.getId() - o2.getId(); // 升序
}
});
System.out.println(stars);
// 使用Lambda表达式 给集合降序排序
Collections.sort(stars, (o1, o2) -> {
return o2.getId() - o1.getId();
});
System.out.println(stars);
// 以上代码当然可以简化了,因为方法体只有一条语句
Collections.sort(stars, ((o1, o2) -> o2.getId() - o1.getId()));
System.out.println(stars);
// 集合工具类默认是升序排序,所以升序排序的话 还可以简化
Collections.sort(stars, (Comparator.comparingInt(Star::getId)));
System.out.println(stars);
}
}
Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作。比如:筛选、排序、聚合 等。
Stream专门为数组和集合打造的 不能用于其他地方。
Stream可以由数组或集合创建,对流的操作分为两种:
Steam可以通过集合或数组创建:
package com.wind.stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
* Stream创建的三种方式
*
* @author Wind
* @date 2021-06-06
*/
public class Test01Stream {
public static void main(String[] args) {
/*
1. Collection集合创建流
*/
List<String> list = Arrays.asList("1", "2", "3", "4", "5");
// 创建一个顺序流
Stream<String> stream = list.stream();
// 创建一个并行流
Stream<String> parallelStream = list.parallelStream();
/*
2. 数组创建流
*/
int[] array = {1, 2, 3, 4, 5};
IntStream arrayStream = Arrays.stream(array);
/*
3. 使用Stream的静态方法:of()、iterate()、generate()
*/
// of()
Stream<Integer> integerStream = Stream.of(1, 2, 3, 4, 5);
// iterate()
Stream<Integer> limitStream = Stream.iterate(0, x -> x + 1).limit(4); // 从0开始,每次+1,循环4次
// generate()
String[] arrString = {"1", "2", "3"};
Stream<String[]> generateStream = Stream.generate(() -> arrString);
}
}
package com.wind.stream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
/**
* Stream的使用:遍历、匹配
*
* @author Wind
* @date 2021-06-06
*/
public class Test02Stream {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
/*
1. 顺序遍历
*/
Stream<Integer> stream = list.stream();
stream.forEach(t -> {
System.out.print(t);
});
System.out.println();
// 简化写法
list.stream().forEach(System.out::print);
System.out.println();
/*
2. 并行遍历:可以理解成多线程
*/
list.parallelStream().forEach(System.out::print);
System.out.println();
/*
3. 匹配:遍历出符合条件的元素
*/
// 遍历大于6的元素:思路是 过滤出大于6的元素,再遍历输出
list.stream().filter(t -> t > 6).forEach(System.out::print);
System.out.println();
// 匹配第一个
Integer int1 = list.stream().findFirst().get();
System.out.println(int1);
// 匹配任意(适用于并行流)
Integer int2 = list.parallelStream().findAny().get();
System.out.println(int2);
// 是否包含符合特定条件的元素
boolean b = list.stream().anyMatch(t -> t == 9);
System.out.println(b);
}
}
package com.wind.stream;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
/**
* Stream的使用:过滤
*
* @author Wind
* @date 2021-06-06
*/
public class Test03Stream {
public static void main(String[] args) {
List<Person> list = new ArrayList<>();
list.add(new Person("张三", 7000, 34, "男", "陕西"));
list.add(new Person("李四", 8000, 24, "男", "河北"));
list.add(new Person("王五", 6000, 42, "女", "甘肃"));
list.add(new Person("王五", 9000, 12, "女", "上海"));
// 工资大于等于8000 并返回新的集合
List<Person> collect = list.stream().filter(t -> t.getSalary() >= 8000).collect(Collectors.toList());
System.out.println(collect);
}
}
package com.wind.stream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* Stream的使用:聚合
*
* @author Wind
* @date 2021-06-06
*/
public class Test04Stream {
public static void main(String[] args) {
// 1. 获取String集合中最长的元素
List<String> strList = Arrays.asList("李白", "张学友", "God");
String s1 = strList.stream().max(((o1, o2) -> o1.length() - o2.length())).get();
System.out.println(s1);
// 上面的简化写法
String s2 = strList.stream().max((Comparator.comparingInt(String::length))).get();
System.out.println(s2);
// 2. 获取Integer集合中的最大值
List<Integer> list = Arrays.asList(7, 6, 9, 3, 8, 2, 1);
Integer maxNum1 = list.stream().max(((o1, o2) -> o1 - o2)).get();
System.out.println(maxNum1);
// 上面的简化写法
Integer maxNum2 = list.stream().max(Integer::compareTo).get();
System.out.println(maxNum2);
// 自然排序
Integer maxNum3 = list.stream().max(Integer::compareTo).get();
// 自定义排序
Integer maxNum4 = list.stream().max(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
}).get();
// 3. 获取员工工资最高的人
List<Person> persons = new ArrayList<>();
persons.add(new Person("张三", 7000, 34, "男", "陕西"));
persons.add(new Person("李四", 8000, 24, "男", "河北"));
persons.add(new Person("王五", 6000, 42, "女", "甘肃"));
persons.add(new Person("王五", 9000, 12, "女", "上海"));
Person person1 = persons.stream().max((o1, o2) -> o1.getSalary() - o2.getSalary()).get();
// 简化写法
Person person2 = persons.stream().max(Comparator.comparingInt(Person::getSalary)).get();
// 4. 计算Integer集合中大于6的元素的个数
long count = list.stream().filter(t -> t > 6).count();
System.out.println(count);
}
}
映射:可以将一个流的元素按照一定的规则映射到另一个流中。
分为:map() 和 flatMap()
package com.wind.stream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
/**
* Stream的使用:映射
*
* @author Wind
* @date 2021-06-06
*/
public class Test05Stream {
public static void main(String[] args) {
// 1. 英文数组的英文全部改为大写
String[] arrStr = {"abcd", "cdfm", "msg", "ssm"};
List<String> list = Arrays.asList(arrStr);
System.out.println(list); // 原来的数组
List<String> newList = list.stream().map(t -> t.toUpperCase(Locale.ROOT)).collect(Collectors.toList());
System.out.println(newList);
System.out.println(list); // 原来的数组
System.out.println("=============================================================");
// 2. 整数数组每个元素+3
List<Integer> integers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> newIntegerList = integers.stream().map(t -> t + 3).collect(Collectors.toList());
System.out.println(integers);
System.out.println(newIntegerList);
System.out.println("=============================================================");
// 3. 将所有员工的薪资增加1000
List<Person> persons1 = new ArrayList<>();
persons1.add(new Person("张三", 7000, 34, "男", "陕西"));
persons1.add(new Person("李四", 8000, 24, "男", "河北"));
persons1.add(new Person("王五", 6000, 42, "女", "甘肃"));
persons1.add(new Person("王五", 9000, 12, "女", "上海"));
// 这种情况会改变原对象的值
List<Person> newpersons1 = persons1.stream().map(t -> {
t.setSalary(t.getSalary() + 1000);
return t;
}).collect(Collectors.toList());
// 原来集合的值被修改了...因为操作的时候是原对象
System.out.println(persons1); // 原来集合的值
System.out.println(newpersons1); // 新集合的值
System.out.println("=============================================================");
// 不改变原有集合值的情况(在修改的时候 new一个新的对象操作)
List<Person> persons2 = new ArrayList<>();
persons2.add(new Person("张三", 7000, 34, "男", "陕西"));
persons2.add(new Person("李四", 8000, 24, "男", "河北"));
persons2.add(new Person("王五", 6000, 42, "女", "甘肃"));
persons2.add(new Person("王五", 9000, 12, "女", "上海"));
List<Person> newPersons2 = persons2.stream().map(t -> {
Person person = new Person(t.getName(), t.getSalary(), t.getAge(), t.getSex(), t.getArea());
person.setSalary(t.getSalary() + 1000);
return person;
}).collect(Collectors.toList());
System.out.println(persons2);
System.out.println(newPersons2);
System.out.println("=============================================================");
// 4. 将两个字符数组 组合成一个新的字符数组
List<String> strings = Arrays.asList("m-k-l-a", "1-2-4-7");
List<String> newStrings = strings.stream().flatMap(t -> {
String[] split = t.split("-");
return Arrays.stream(split);
}).collect(Collectors.toList());
System.out.println(strings);
System.out.println(newStrings);
}
}
规约,也称缩减,顾名思义就是把一个流缩减成一个值,能实现对集合求和、求乘积、求最值操作
package com.wind.stream;
import java.util.Arrays;
import java.util.List;
/**
* Stream的使用:规约
*
* @author Wind
* @date 2021-06-06
*/
public class Test06Stream {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 3, 2, 8, 11, 4);
/*
求和
*/
// 求和方式一:调用Integer的sum()方法
Integer sum1 = list.stream().reduce(Integer::sum).get();
System.out.println(sum1);
// 求和方式二:同方式一 多了一个初始值。怎么理解呢?类似于原来的写法 定义一个 int sum = 0,遍历集合后 sum+=。下面方法的第一个参数类似于 定义的 sum = 0
Integer sum2 = list.stream().reduce(0, Integer::sum);
System.out.println(sum2);
// 求和方式三:
Integer sum3 = list.stream().reduce((x, y) -> x + y).get();
System.out.println(sum3);
/*
求乘积
*/
Integer cj = list.stream().reduce((x, y) -> x * y).get();
System.out.println(cj);
/*
求最大值
*/
// 方式一:Stream的max()方法
Integer max1 = list.stream().max(Integer::compareTo).get();
System.out.println(max1);
// 方式二:自己实现比较 最后返回比较结果
Integer max2 = list.stream().reduce((x, y) -> x > y ? x : y).get();
System.out.println(max2);
// 方式三:利用Integer的max()方法
Integer max3 = list.stream().reduce(Integer::max).get();
System.out.println(max3);
}
}
因为流不存储数据,那么在流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。toList、toSet、toMap比较常用,另外还有toCollection、toConcurrentMap等复杂一些的用法。
package com.wind.stream;
import java.util.*;
import java.util.stream.Collectors;
/**
* Stream的使用:归集
*
* @author Wind
* @date 2021-06-09
*/
public class Test07Stream {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 6, 3, 4, 4, 5, 7, 9, 6, 21);
list.forEach(System.out::print);
System.out.println();
// toList
List<Integer> newList = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
newList.forEach(System.out::print);
System.out.println();
// toSet
Set<Integer> newSet = list.stream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
newSet.forEach(System.out::print);
System.out.println();
// toMap
List<Person> persons = new ArrayList<>();
persons.add(new Person("张三", 7000, 34, "男", "陕西"));
persons.add(new Person("李四", 8000, 24, "男", "河北"));
persons.add(new Person("王五", 6000, 42, "女", "甘肃"));
persons.add(new Person("王五", 9000, 12, "女", "上海"));
Map<String, Person> map = persons.stream().filter(p -> p.getSalary() > 6000).collect(Collectors.toMap(Person::getName, p -> p));
System.out.println(map);
}
package com.wind.stream;
import java.util.ArrayList;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.stream.Collectors;
/**
* Stream的使用:统计
*
* @author Wind
* @date 2021-06-09
*/
public class Test08Stream {
public static void main(String[] args) {
List<Person> persons = new ArrayList<>();
persons.add(new Person("张三", 7000, 34, "男", "陕西"));
persons.add(new Person("李四", 8000, 24, "男", "河北"));
persons.add(new Person("王五", 6000, 42, "女", "甘肃"));
persons.add(new Person("王五", 9000, 12, "女", "上海"));
// 求总数
Long count = persons.stream().collect(Collectors.counting());
System.out.println(count);
// 求平均工资
Double average = persons.stream().collect(Collectors.averagingDouble(Person::getSalary));
System.out.println(average);
// 求最高工资
Integer max = persons.stream().map(t -> t.getSalary()).collect(Collectors.maxBy(Integer::compareTo)).get();
System.out.println(max);
// 求工资之和
Double sum = persons.stream().collect(Collectors.summingDouble(Person::getSalary));
System.out.println(sum);
// 一次性统计所有(总结)
DoubleSummaryStatistics summarizing = persons.stream().collect(Collectors.summarizingDouble(Person::getSalary));
System.out.println(summarizing); // DoubleSummaryStatistics{count=4, sum=30000.000000, min=6000.000000, average=7500.000000, max=9000.000000}
System.out.println(summarizing.getCount());
System.out.println(summarizing.getSum());
System.out.println(summarizing.getMin());
System.out.println(summarizing.getAverage());
System.out.println(summarizing.getMax());
}
}
package com.wind.stream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Stream的使用:分组
*
* @author Wind
* @date 2021-06-09
*/
public class Test09Stream {
public static void main(String[] args) {
List<Person> persons = new ArrayList<>();
persons.add(new Person("张三", 7000, 34, "男", "陕西"));
persons.add(new Person("李四", 8000, 24, "男", "河北"));
persons.add(new Person("王五", 6000, 42, "女", "甘肃"));
persons.add(new Person("王五", 9000, 12, "女", "上海"));
// 分区:将员工薪资按照是否高于7000分区
Map<Boolean, List<Person>> partitioning = persons.stream().collect(Collectors.partitioningBy(x -> x.getSalary() > 7000));
System.out.println(partitioning);
// 分组:将员工按照性别分组
Map<String, List<Person>> grouping1 = persons.stream().collect(Collectors.groupingBy(Person::getSex));
System.out.println(grouping1);
// 分组:将员工先按照性别分组,再按照地区分组
Map<String, Map<String, List<Person>>> grouping2 = persons.stream().collect(Collectors.groupingBy(Person::getSex, Collectors.groupingBy(Person::getArea)));
System.out.println(grouping2);
}
}
joining可以将Stream中的元素用特定的连接符(没有的话,则直接连接)连接成一个字符串
package com.wind.stream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* Stream的使用:接合
*
* @author Wind
* @date 2021-06-09
*/
public class Test10Stream {
public static void main(String[] args) {
List<Person> persons = new ArrayList<>();
persons.add(new Person("张三", 7000, 34, "男", "陕西"));
persons.add(new Person("李四", 8000, 24, "男", "河北"));
persons.add(new Person("王五", 6000, 42, "女", "甘肃"));
persons.add(new Person("王五", 9000, 12, "女", "上海"));
// 将员工姓名用 “,” 拼接
String nameStr = persons.stream().map(p -> p.getName()).collect(Collectors.joining(","));
System.out.println(nameStr);
List<String> strings = Arrays.asList("A", "B", "C", "D");
// 将集合元素拼接成字符串
String str = strings.stream().collect(Collectors.joining("-"));
System.out.println(str);
}
}
sorted中间操作。有两种排序:
package com.wind.stream;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* Stream的使用:排序
*
* @author Wind
* @date 2021-06-09
*/
public class Test11Stream {
public static void main(String[] args) {
List<Person> persons = new ArrayList<>();
persons.add(new Person("张三", 7000, 34, "男", "陕西"));
persons.add(new Person("李四", 8000, 42, "男", "河北"));
persons.add(new Person("王五", 8000, 24, "女", "甘肃"));
persons.add(new Person("王五", 9000, 12, "女", "上海"));
// 将员工工资升序排序(自然排序)【从小到大】
List<Person> sorted1 = persons.stream().sorted(Comparator.comparing(Person::getSalary)).collect(Collectors.toList());
sorted1.forEach(System.out::println);
System.out.println();
// 将员工工资降序排序(倒序排序)【从大到小】
List<Person> sorted2 = persons.stream().sorted(Comparator.comparing(Person::getSalary).reversed()).collect(Collectors.toList());
sorted2.forEach(System.out::println);
System.out.println();
// 先按工资 再按年龄,升序排序
List<Person> sorted3 = persons.stream().sorted(Comparator.comparing(Person::getSalary).thenComparing(Person::getAge)).collect(Collectors.toList());
sorted3.forEach(System.out::println);
}
}
流也可以进行 合并、去重、限制、跳过 等操作
package com.wind.stream;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Stream的使用:提取/组合
*
* @author Wind
* @date 2021-06-09
*/
public class Test12Stream {
public static void main(String[] args) {
String[] arr1 = {"a", "b", "c", "d"};
String[] arr2 = {"d", "e", "f", "g"};
Stream<String> stream1 = Stream.of(arr1);
Stream<String> stream2 = Stream.of(arr2);
// concat:合并两个流,去重
List<String> arr = Stream.concat(stream1, stream2).distinct().collect(Collectors.toList());
arr.forEach(System.out::print);
System.out.println();
// limit:限制从流中获得前n个数据
List<Integer> limit = Stream.iterate(1, t -> t + 2).limit(10).collect(Collectors.toList());
limit.forEach(t -> System.out.print(t + ","));
System.out.println();
// skip:跳过前n个数据
List<Integer> skip = Stream.iterate(1, t -> t + 2).skip(2).limit(5).collect(Collectors.toList());
skip.forEach(t -> System.out.print(t + ",")); // 跳过了 1和3
}
}