两大核心
lambda表达式 || Stream API表达式
lambda表达式
格式:<函数式接口><变量名> = (参数1,参数2)->{ 方法体 }
特点:形参列表的数据类型会自动判断
如果形参列表为空,只需保留()
如果形参只有1个,()可以省略,只需要参数名称
如果执行语句只有一句,无返回值,{}可以省略 || 若有返回值省去{},必须同时省略return,执行语句也只有一句
例:Runnable r = ()->{sout("这是lambda表达式");};
Thread t = new Thread(r); //简写:Thread t = new Thread(()->{sout("这是lambda表达式");});
t.start();
//=====等价于======匿名内部类
Runnable r =new Runnable(){
public void run(){
sout("这是匿名内部类方式")
}
};
Thread t =new Thread(r);
t.start();
//对集合中的元素按照年龄进行排序---普通方法
personList.add(new Person("aa",50));
personList.add(new Person("bb",55));
personList.add(new Person("cc",57));
personList.add(new Person("dd",34));
Comparator<Person> c = new Comparator<Person>(){
public int co(Person p1,Person p2){
return p2.getAge() - p1.getAge(); //0表示对比两个值相同 || 1表示小 || 2表示大
}
}
Collections.sort(personList, c); //使用排序规则
//使用lambda
Comparator<Person> comparator = (Person p1,Person p2)->{
return p2.getAge() - p1.getAge();
};
Collections.sort(personList, c);
函数式接口
内置函数式接口的由来
public class Test{
main{
Operater o = arr->{
int sum=0;
for(int n:arr){
sum+=n;
}
}
fun(o)
}
public static void fun(Operater o){
int[] arr = {2,3,4,5,6,7,8};
o.getSum(arr);
}
}
interface Operater{
public abstract void getSum(int[] arr);
}
消费型函数 --consumer
有参数无返回值
main{
Consumer<Double> c =m->{
sout("洗脚花了"+m)
};
fun(c,200)
}
public static void fun(Consumer<Double> consumer,double money){
consumer.accept(money);
}
供给型函数 --supplier<T>
无参,有返回结果的函数式接口
T get()
main{fun(()->new Random().nextInt(10));}
public static void fun(supplier<Integer> supplier){
Integer r = supplier.get();
sout("内容为:"+)
}
函数型接口 --Function<T,R>
T:参数类型泛型 R:函数返回结果泛型
有参有返回值
//例子:传入字符串把小写转换大写
main{
fun((t)->{
return t.toUpperCase()
},"aaa");
}
public static void fun(Function<String,String> function,String msg){
String s =function.apply(msg)
}
//BiFunctin --Function的补充版
//BiFunction<T,U,R> ||T:参数一 U:参数二 R:返回类型
BiFunction<String,String,Boolean> bi = (t,u)->t.equals(u);
断言型 --Predicated<T>
T:参数的泛型
boolean test(T t)
传入参数时需要对该参数进行判
main{
fun(n->{
return n.length()>3?true:false;
},"哈哈")
}
public static void fun(Predicate<String> predicate,String name){
boolean b = predicate.test(name)
}
方法引用
lambda表达式冗余
如果在其他地方已经有相同的业务逻辑代码,重复写会产生冗余,这时就用到了方法引用
其中的双冒号::称为方法引用
public class Test{
public static void main(String[] args){
// Consumer<Integer[]> c = arr->{
// int sum=0;
// for(int b:arr){
// sum+=b;
//}
//} 等价于------------>双冒号::方法引用
Consumer<Integer[]> c = Test::sum;
fun(c);
}
public static void fun(Consumer<Integer[]> c){
Integer[] arr = {1,2,3,4,5};
c.accept(arr);
}
public static void sum(Integer[] arr){
int sum=0;
for(int a:arr){
sum+=a;
}
}
}
方法引用分类
静态方法 || 实例方法 || 对象方法 || 构建方法
如果在lambda表达式中仅有一条语句,而且这条语句符合方法引用的格
静态方法
语法:类名::静态方法
lambda表达式:(参数)->类名.静态方法(参数) || 参数需要保持一致
public static void main(String[] args){
List<Integer> list = new ArrayList<>();
//添加元素
list.add(1);
list.add(2);
list.add(3);
//lambda
Comparator<Integer> c = (o1,o2)->o1-o2;
//lambda引用方法自带的排序
Comparator<Integer> c = (o1,o2)->Integer.compare(o1,o2);
//静态方法使用
Comparator<Integer> c = Integer::compare;
//使用排序方法
list.sort(c);
}
实例方法
语法:实例对象::实例对象方法
lambda表达式:(参数)->实例对象.实例方法(参数) || 参数需保持一致
People p =new People("aa",25);
//lambda
Supplier<String> s =()->p.getName;
//实例方法引用
Supplier<String> s =p::getName;
//功能方法
public static void fun(Supplier<String> supplier){
String s = supplier.get();
}
//方法调用
fun(s);
对象方法
语法:类名::实例方法
lambda表达式:(实例对象,参数)->实例对象.实例方法(参数) || 参数要么保持一致,要么都没有参数
main(){
//lambda
BiFunction<String,String,Boolean> bi = (t,u)->{
return t.equals(u);
}
//对象方法引用
BiFunction<String,String,Boolean> bi = String::equals;
//比较两个字符串是否相同
Boolean b = bi.apply("bbb","aaa")
}
构建方法
语法:类名::new
lambda表达式:参数->new 类名(参数) || 参数保持一致
main{
//lambda
Function<String,People> function = (n)->new People(n);
//构建方法引用
Function<String,people> function = People::new;
People p = function.apply("aaa")
}
Stream流
原理
Stream和IO流没有任何关系
Sream不是一种数据结构,不保存数据,只对数据进行加工处理
获取流的方法
流分为串行流和并行流
如果流中的数据量足够大,并行流可以加快处理速度
串行流
//通过集合对象调用Stream()
List<String> list = new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
list.add("ddd");
Stream<String> s = list.stream();
//通过Arrays数组工具类获取Stream对象
int[] arr = {3,4,5,6,7,8,1};
IntStream s = Arrays.stream(arr);
//使用Stream类的of方法
Stream<String> s = Stream.of("a","b","c","d");
//LongStream
LongStream s = LongStream.range(1,10); //获取1-9的所有数字
LongStream s = LongStream.rangeClosed(1,10); //获取1-10的所有数字
并行流
Stream<String> s = list.parallelStream();
Stream常用方法
无论执行多少中间操作,如果没有执行终止操作,那么中间操作不会被执行
终止操作一次只能调用一个
中间操作:.filter(断言型) --过滤器
.map() --将流中元素转换为另一种格式
.sorted() --排序
终止操作:.forEach(消费型) --遍历
.count() --计数
.max() --最大值
.min() --最小值
.reduce --规约 ||也称缩减,把一个流缩减成一个值,能实现对集合求和求积求最值 .collect() --搜集方法
.findFirst() --查找第一个符合条件的元素
.findAny() --随机从符合条件的元素中查找一个,适用于并行流
.allMatch() --所有都符合要求则返回true
.noneMatch() --所有都不符合要求返回true
.anyMatch() --部分符合要求返回true
main{
ArrayList(String) list = new ArrayList<>();
Collections.addAll(list,"张三","李四","王五","赵六");
boolean b = personList.parallelStream()
.noneMatch(item->item.getAge()>20) //集合中不包含年龄大于20的返回true
.allMatch(item->item.getAge()>20) //所有年龄都大于20返回true
.anyMatch(item->item.getAge()>20) //部分年龄大于20返回true
sout(b)
Optional<Person> f = personList.parallelStream()
.filter(item->item.getSex()=="张三")
.findAny();
sout(f.get()) //随机从流中获取一个名称为张三的元素
Optional<Person> first = personList.stream().filter(item->item.getName()=="张三")
.findFirst();
sout(first.get()); //获取第一个name为张三的元素
List<Person> collect = personList.stream()
.filter(item.getAge()>20)
.filtere(item->item.getName()=='张三')
.collect(Collectors.toList()); //将年龄大于20,姓名为张三的搜集起来
Optional<Integer> r = personList.stream()
.map(item -> item.getAge())
.reduce((a,b) -> a+b); //参数和返回类型必须一致,所以先用map将所有age取出
//.reduce(10,(a,b)->a+b); //代表初始值为10
sout(r.get());
Optional<Person> max = personList.stream()
.max((o1,o2)->o1.getAge() - o2.getAge());
sout(max) //查找年龄最大的,并输出 ||最小值类似 ||假设有年龄属性
list.stream().filter(item->item.startsWith("李")) //将集合转换为流,并过滤出姓李的
.sorted((o1,o2)->o1.getAge()-o2.getAge()) //按照年龄排序 ||假设有年龄属性
.map(item->{ //新建一个哈希map,将name和age放入其中 ||假设有age属性
Map<String, Object> m = new HashMap<>();
m.put("name",item.getName());
m.put("age",item.getAge());
return m;
})
.filter(item->item.getName().equals("王五")).count(); //计算出名字为王五的数量
.forEach(System.out::println); //输出过滤后的内容
}