出自:https://blog.csdn.net/qq_28410283/article/details/80601495
Lambda 表达式:
//1.Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
//2.Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
//3.使用 Lambda 表达式可以使代码变的更加简洁紧凑。
/*以下是lambda表达式的重要特征:
可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。*/
1. 左侧:lambda表达式的参数列表
2. 右侧:lambda表达式中所需要执行的功能,即lambda函数体
3 .lambda表达式语法格式有三种:
1).无参数,无返回值的用法 :( ) -> System.out.println("hello lambda");
2). 有一个参数,无返回值的用法: (x) -> System.out.println(x); 或者 x -> System.out.println(x); 一个参数,可以省略参数的小括号
3)有两个参数,有返回值的:(x, y) -> x + y
public void test4() {
// 无返回值lambda函数体中用法
//多行的,只需要用大括号{}把语句包含起来就可以了
//只有一条语句的,大括号可以不用写;
Runnable r1 = () -> {
System.out.println("hello lambda1");
System.out.println("hello lambda2");
System.out.println("hello lambda3");
};
r1.run();
// 有返回值lambda函数体中用法
//有返回值和无返回值的,只有一个return的区别
//只有一条语句的,renturn都可以不用写;
BinaryOperator<Integer> binary = (x, y) -> {
int a = x * 2;
int b = y + 2;
return a + b;
};
System.out.println(binary.apply(1, 2));// 6
}
2.方法的引用的语法,主要有三类
1.指向静态方法的方法引用,例如Integer的parseInt方法 ,可以写成 Integer::parseInt
类::静态方法名
2.指向任意类型实例方法的方法引用,例如String的length方法,写成 String::length;
类::实例方法名
3.指向现有对象的实例方法的方法引用
对象::实例方法名
构造器的引用:对于一个现有构造函数,你可以利用它的名称和关键字new来创建它的一个引用ClassName::new;
public static void main(String args[]){
/*************** 方法的引用 ****************/
// 类::静态方法名
Comparator<Integer> cam1 = (x, y) -> x.compareTo(y);
System.out.println(cam1.compare(2, 4));
Comparator<Integer> cam = Integer::compareTo;
System.out.println(cam.compare(3, 2));
// 类::实例方法名
BiPredicate<String, String> bp = (x, y) -> x.equals(y);
System.out.println(bp.test("a", "b"));
BiPredicate<String, String> bp1 = String::equals;
System.out.println(bp1.test("a", "b"));
// 对象::实例方法名
Consumer<String> con1 = x -> System.out.println(x);
con1.accept("abc");
Consumer<String> con = System.out::println;
con.accept("abc");
Emp emp = new Emp("上海", "xiaoMIng", 18);
Supplier<String> supper1 = () -> emp.getAddress();
System.out.println(supper1.get());
Supplier<String> supper = emp::getAddress;
System.out.println(supper.get());
/*************** 构造器的引用 ****************/
// 无参构造函数,创建实例
Supplier<Emp> supper2 = () -> new Emp();
Supplier<Emp> supper3 = Emp::new;
Emp emp1 = supper3.get();
emp1.setAddress("上海");
System.out.println("emp1="+emp1.toString());
// 一个参数
Function<String, Emp> fun = address -> new Emp(address);
Function<String, Emp> fun1 = Emp::new;
System.out.println("beijing="+fun1.apply("beijing"));
// 两个参数
BiFunction<String, Integer, Emp> bFun = (name, age) -> new Emp(name, age);
BiFunction<String, Integer, Emp> bFun1 = Emp::new;
System.out.println("xiaohong="+bFun1.apply("xiaohong", 18));
}
3、java8 函数式接口简介:https://blog.csdn.net/qq_28410283/article/details/80962325
4、Stream接口简介: 流是java API中的新的成员,它可以让你用声明式的方式处理集合,简单点说,可以看成遍历数据的一个高级点的迭代器。
1.Arrays.stream,我们可以通过Arrays的静态方法,传入一个泛型数组,创建一个流。
2.Stream.of,我们可以通过Stream的静态方法,传入一个泛型数组,或者多个参数,创建一个流,这个静态方法,也是调用了Arrays的stream静态方法,如下
System.out.println(Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3));
通过stream里面抽象方法的定义,我们可以看到,这个方法,可以分成两种类型,一种返回类型为接口本身的Stream<T>,另外一种是返回其他对象类型的,返回接口类型的,我们称这些方法为中间操作,返回其他具体类型的,我们称为终端操作;
5、Stream接口之
⑥对对象的操作:peek
⑥统计个数:count
⑦取用前几个:limit
⑧跳过前几个:skip
⑨组合数组:concat
⑩排序:sorted:
sorted() 自然排序
sorted(Comparator com) 定制排序
allMatch 检查是否匹配所有元素
anyMatch 检查是否至少匹配一个元素
noneMatch 检查是否没有匹配所有元素
findFirst 返回第一个元素
findAny 返回当前流中的任意元素
count 返回流中元素的总个数
max 返回流中最大值
min 返回流中最小值
?Collect: 将流转换为其他形式。接收一个Collector的实现,用于给stream中元素做汇总的方法。
?map映射, 用来归类,结果一般是一组数据,比如可以将list中的学生分数映射到一个新的stream中。
?reduce规约, 用来计算值,结果是一个值,比如计算最高分。
④flatMap 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。即对流扁平化处理,浅显一点解释就是把几个小的list转换到一个大的list
6.并行流和顺序流:
并行流是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。
通过parallel()与sequential()可以实现并行流和顺序流之间的切换。
7、流的实例用法demo:
package jdk18meths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class TestJava8 {
public static List<Emp> list = new ArrayList<>();
static {
list.add(new Emp("xiaoHong1", 20, 1000.0));
list.add(new Emp("xiaoHong2", 25, 2000.0));
list.add(new Emp("xiaoHong3", 30, 3000.0));
list.add(new Emp("xiaoHong4", 35, 4000.0));
list.add(new Emp("xiaoHong5", 38, 5000.0));
list.add(new Emp("xiaoHong6", 45, 9000.0));
list.add(new Emp("xiaoHong7", 55, 10000.0));
list.add(new Emp("xiaoHong8", 42, 15000.0));
}
public static void main(String[] args) {
// 对数组流,先过滤重复,在排序,再控制台输出 1,2,3
List arr =Arrays.asList(3, 1, 2, 1).stream().distinct().sorted().collect(Collectors.toList());
System.out.println(arr);
// 对list里的emp对象,取出薪水,并对薪水进行排序,然后输出薪水的内容,map操作,改变了Strenm的泛型对象
List list2= list.stream().map(emp -> emp.getSalary()).sorted().collect(Collectors.toList());
System.out.println(list2);
//peek 给年纪大于30岁的人,薪水提升1.5倍,并输出结果
List<Emp> stream = list.stream().filter(emp -> {
return emp.getAge() > 30;
}).peek(emp -> {
emp.setSalary(emp.getSalary() * 1.5);
}).collect(Collectors.toList());
stream.forEach(s -> System.out.println(s.getName()));
System.out.println("stream="+stream.toString());
//peek
List list = Stream.of("one", "two", "three", "four").filter(e -> e.length() > 3).peek(e -> e.equals("four"))
.map(String::toUpperCase).collect(Collectors.toList());
System.out.println(list);
//把2个数组组合在一起
Stream<String> stream1 = Stream.of("陈奕迅", "陈伟霆", "陈七", "钟汉良");
String[] arr2 = {"1","2","3"};
Stream<String> stream2 = Stream.of(arr2);
Stream<String> concatStream = Stream.concat(stream1, stream2);
concatStream.forEach(str-> System.out.println(str));
System.out.println(concatStream);
//另一种方法:flatMap
//接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。即对流扁平化处理,浅显一点解释就是把几个小的list转换到一个大的list
}
public static class Emp {
@Override
public String toString() {
return "Emp [name=" + name + ", age=" + age + ", salary=" + salary + "]";
}
private String name;
private Integer age;
private Double salary;
public Emp(String name, Integer age, Double salary) {
super();
this.name = name;
this.age = age;
this.salary = salary;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Double getSalary() {
return salary;
}
public void setSalary(Double salary) {
this.salary = salary;
}
}
}
package jdk180reduce;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class StreamTest01 {
public static void main(String[] args) {
List<Student> stuList = new ArrayList<>(10);
stuList.add(new Student("刘一", 85));
stuList.add(new Student("陈二", 90));
stuList.add(new Student("张三", 98));
stuList.add(new Student("李四", 88));
stuList.add(new Student("王五", 83));
stuList.add(new Student("赵六", 95));
stuList.add(new Student("孙七", 87));
stuList.add(new Student("周八", 84));
stuList.add(new Student("吴九", 100));
//需求:列出90分以上的学生姓名,并按照分数降序排序
List<Student> result1 = new ArrayList<>(10);
result1 = stuList.stream().filter(s -> s.getScore()>=90)
.sorted(Comparator.comparing(Student :: getScore).reversed())
.collect(Collectors.toList());
System.out.println(result1); //list.stream().sorted(Comparator.reverseOrder());
//计算学生总分 2个参数:初始值(即0+a[1]+a[2]+...)开始一直相加, //reduce用来计算值,结果是一个值,比如计算最高分。
Integer totalScore1 = stuList.stream().map(Student::getScore).reduce(0,(a,b) -> a + b);
System.out.println("totalScore1="+totalScore1);
//计算学生总分,一个参数忽略a[0] 返回Optional类型的数据,改类型是java8中新增的,主要用来避免空指针异常
Optional<Integer> totalScore2 = stuList.stream().map(Student::getScore).reduce((a,b) -> a + b);
System.out.println("totalScore2="+totalScore2.get());
//计算最高分和最低分
Optional<Integer> max = stuList.stream().map(Student::getScore).reduce(Integer::max);
Optional<Integer> min = stuList.stream().map(Student::getScore).reduce(Integer::min);
System.out.println("max="+max.get());
System.out.println("min="+min.get());
//stream没有sum求和的方法,但是有别的。
//将stream转换为IntStream求和
int totalScoreInt = stuList.stream().mapToInt(Student::getScore).sum();
System.out.println("Int_totalScore="+totalScoreInt);
//计算平均分
OptionalDouble avgScore = stuList.stream().mapToInt(Student::getScore).average();
System.out.println("avgScore="+avgScore.getAsDouble());
//生成1~100之间的数字
IntStream num = IntStream.rangeClosed(1, 100);
System.out.println("num="+num.toString());
List<String> lists = new ArrayList<>();
lists.add("li");
lists.add("zhang");
lists.add("chen");
//Match匹配
boolean a = lists.stream().anyMatch(s -> s.startsWith("li"));
System.out.println("li = " + a);
//判断是否全为li开头的
System.out.println(lists.stream().allMatch(s -> s.startsWith("li")));
//判断一个字符在该集合中不存在
System.out.println(lists.stream().noneMatch(s -> s.startsWith("li2")));
//filter: filter方法的作用,是对这个boolean做判断,返回true判断之后的对象
//返回字符串为a的值
String[] dd = { "a", "b", "c" };
java.util.stream.Stream<String> stream = Arrays.stream(dd);
stream.filter(str -> str.equals("c")).forEach(System.out::println);
}
}
package jdk180reduce;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalDouble;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
public class TestJava8 {
public static List<Emp> list = new ArrayList<>();
static {
list.add(new Emp("上海", "小名", 17));
list.add(new Emp("北京", "小红", 18));
list.add(new Emp("深圳", "小蓝", 19));
list.add(new Emp("广州", "小灰", 20));
list.add(new Emp("杭州", "小黄", 21));
list.add(new Emp("贵阳", "小白", 22));
}
public static void main(String[] args) {
// 转list
List<String> names = list.stream().map(e -> e.getName()).collect(Collectors.toList());
System.out.println("names="+names);
// 转set
Set<String> address = list.stream().map(emp -> emp.getName()).collect(Collectors.toSet());
System.out.println("address="+address);
// 转map,需要指定key和value,Function.identity()表示当前的Emp对象本身
Map<String, Emp> map = list.stream().collect(Collectors.toMap(Emp::getName, Function.identity()));
System.out.println("转map="+map);
// 计算元素中的个数
Long count = list.stream().collect(Collectors.counting());
// 数据求和 summingInt summingLong,summingDouble
Integer sumAges = list.stream().collect(Collectors.summingInt(Emp::getAge));
int totalScoreInt = list.stream().mapToInt(Emp::getAge).sum();
System.out.println("求和="+sumAges);
System.out.println("求和2="+totalScoreInt);
// 平均值 averagingInt,averagingDouble,averagingLong
Double aveAges = list.stream().collect(Collectors.averagingInt(Emp::getAge));
OptionalDouble avgScore = list.stream().mapToInt(Emp::getAge).average();
System.out.println("平均值 1="+aveAges);
System.out.println("平均值 2="+avgScore);
// 综合处理的,求最大值,最小值,平均值,求和操作
// summarizingInt,summarizingLong,summarizingDouble
IntSummaryStatistics intSummary = list.stream().collect(Collectors.summarizingInt(Emp::getAge));
System.out.println(intSummary.getAverage());// 19.5
System.out.println(intSummary.getMax());// 22
System.out.println(intSummary.getMin());// 17
System.out.println(intSummary.getSum());// 117
// 连接字符串,当然也可以使用重载的方法,加上一些前缀,后缀和中间分隔符
String strEmp = list.stream().map(emp -> emp.getName()).collect(Collectors.joining());
String strEmp1 = list.stream().map(emp -> emp.getName()).collect(Collectors.joining("-中间的分隔符-"));
String strEmp2 = list.stream().map(emp -> emp.getName()).collect(Collectors.joining("-中间的分隔符-", "前缀*", "&后缀"));
// 小名小红小蓝小灰小黄小白
// 小名-中间的分隔符-小红-中间的分隔符-小蓝-中间的分隔符-小灰-中间的分隔符-小黄-中间的分隔符-小白
// 前缀*小名-中间的分隔符-小红-中间的分隔符-小蓝-中间的分隔符-小灰-中间的分隔符-小黄-中间的分隔符-小白&后缀
System.out.println(strEmp);
System.out.println(strEmp1);
System.out.println(strEmp2);
// maxBy 按照比较器中的比较结果刷选 最大值
Optional<Integer> maxAge = list.stream().map(emp -> emp.getAge()).collect(Collectors.maxBy(Comparator.comparing(Function.identity())));
// 最小值
Optional<Integer> minAge = list.stream().map(emp -> emp.getAge()).collect(Collectors.minBy(Comparator.comparing(Function.identity())));
System.out.println("max:" + maxAge);
System.out.println("min:" + minAge);
// 归约操作
list.stream().map(emp -> emp.getAge()).collect(Collectors.reducing((x, y) -> x + y));
list.stream().map(emp -> emp.getAge()).collect(Collectors.reducing(0, (x, y) -> x + y));
// 分操作 groupingBy 根据地址,把原list进行分组
Map<String, List<Emp>> mapGroup = list.stream().collect(Collectors.groupingBy(Emp::getAddress));
System.out.println("mapGroup:" + mapGroup);
// partitioningBy 分区操作 需要根据类型指定判断分区
Map<Boolean, List<Integer>> partitioningMap = list.stream().map(emp -> emp.getAge()).collect(Collectors.partitioningBy(emp -> emp > 20));
System.out.println("partitioningMap:" + partitioningMap);
}
static class Emp {
private String address;
private String name;
private Integer age;
public Emp() {
}
public Emp(String address) {
this.address = address;
}
public Emp(String name, Integer age) {
this.name = name;
this.age = age;
}
public Emp(String address, String name, Integer age) {
super();
this.address = address;
this.name = name;
this.age = age;
}
//get set 方法
}