文章目录
Java8新特性
lambda表达式
常规写法
Runnable ra = new Runnable() {
@Override
public void run() {
System.out.println("你好");
}
};
ra.run();
lambda表达式
Runnable ra2 = () -> System.out.println("你也好");
ra2.run();
语法格式
无参,无返回值
() -> System.out.println("你也好")
一参,无返回值
当只有一个参数时,小括号也可以省
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("我爱你中国");
编译器会自动进行类型推断,所以说s前面不用写类型了,并且s外围的小括号可省略
Consumer<String> con = (s) -> {
System.out.println(s);
};
con.accept("我爱你中国");
多参,有返回值
Comparator<Integer> com = (o1, o2)-> {
if(o1>o2)
return 1;
else
return 0;
};
int a = com.compare(10,9);
System.out.println(a);
方法体只有一语句
大括号可省,若有return则也省掉
Comparator<Integer> com = (o1, o2)-> Integer.compare(o1,o2);
int a = com.compare(10,19);
System.out.println(a);
函数式接口
只有一个抽象方法的接口,通过lambda表达式创建函数式接口的对象
自定义函数式接口
@FunctionalInterface
interface myinter{
void method1();
}
四大接口
名字 | 抽象方法 | 解释 |
---|---|---|
消费型接口 Consumer | void accept(T t) | 类似于消费者,只接受,不输出 |
供给型接口 Supplier | T get() | 类似于生产者,只输出,不接受 |
函数型接口 Function<T,R> | R apply(T t) | 根据某种函数式关系将T类型转化为R类型 |
断定型接口 Predicate | boolean test(T t) | 判断真假 |
比较器借口 Compartor | int Compare(T t) | 比较大小 |
举例:
public class lambdaTest {
public static void main(String[] args) {
preson pre = new preson();
pre.happyTime(1000,(money)-> System.out.println("今天花了"+ money));
这里传进去了一个lambda表达式,也就是匿名对象
}
}
class preson{
public void happyTime(int money , Consumer<Integer> com){
com.accept(money);
}
}
筛选出第一个字符是“我”的字符串
public class lambdaTest {
public static void main(String[] args) {
LinkedList<String> a = new LinkedList<>();
for(int i = 0;i<8;i++) {
if(i%2==0)
a.add("我" + i);
else
a.add("你" + i);
}
preson pre = new preson();
pre.test(a , q -> q.charAt(0)=='我');
}
}
class preson{
public void test(LinkedList<String> sr , Predicate<String> pr){
LinkedList<String> str = new LinkedList<>();
for(String s : sr){
if(pr.test(s))
str.add(s);
}
for(String s : str)
System.out.println(s);
}
}
方法引用
当传递给Lambda体的操作已经有实现方法了,可以使用方法引用
方法体的参数列表和返回值 要和 抽象方法的一样
使用情景:
对象::实例方法名
类::静态方法名
Comparator<Integer> com = (o1, o2)-> Integer.compare(o1,o2);
int a = com.compare(10,19);
System.out.println(a);
方法引用:
Comparator<Integer> com1 = Integer::compare;
int a1 = com.compare(10,19);
System.out.println(a1);
使用情景2:
类::实例方法名
Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2); 此处是s1调用函数,而不是某个类调用
System.out.println(com1.compare("abc","abd"));
方法引用:
Comparator<String> com1 = String::compareTo;
System.out.println(com1.compare("abc","abd"));
构造器引用
用来创建新对象
Supplier<Employee> sup = () -> new Employee();
或者构造器引用
Supplier<Employee> sup1 = Employee::new;
数组引用
用来创建数组
Function<Integer , String[]> fun = len -> new String[len];
System.out.println(fun.apply(10).length);
Stream
steam是数据渠道,用于操作数据源所生成的元素序列
集合讲的是数据,stream讲的是计算
特点:
- Stream不会存储元素
- Stream不会改变源对象,会返回一个新的Stream
- Stream的操作是延迟的,他们会等到需要最终结果的时候才执行
执行流程:
- Stream的实例化。从数据源获取一个流…
- 一系列的中间操作(过滤,映射…)。是一个中间操作链,对数据进行处理…
- 终止操作。一旦执行终止操作,就计算中间操作链,产生结果。后面的代码不能再调用这个stream对象
创建
通过集合创建
返回顺序流,能保证原数据的顺序
Stream<String> str = list.stream();
返回并行流
Stream<String> str1 = list.parallelStream();
通过数组创建
通过数组
String[] list1 ={"赵","钱","孙","菅"};
Stream<String> str3 = Arrays.stream(list1);
通过stream的of
通过stream的of
Stream<String> str4 = Stream.of("赵","钱","孙","菅");
还能创建无限大的stream流,此处没写
中间操作
筛选与切片
首先创建一个stream流,命名为str
中间操作,会返回一个新的stream
filter(Predicate p) 过滤
limit(n) 截断流,仅限取前n个元素
skip(n) 跳过元素
distinct() 去重
forEach里面是一个消费者,只进不出
下面这几个语句不能同时执行,因为一个stream对象只能用一次
str.filter( (s) -> s.startsWith("刘")).forEach(System.out::println);
str.limit(3).forEach(System.out::println);
str.skip(3).forEach(System.out::println);
str.distinct().forEach(System.out::println);
映射
map映射。接受的是一个Function
str.map(String::length).filter(s1 -> s1>3).forEach(System.out::println);
flatmap()
有时候会一个stream里面每个元素都是额外一个stream,比如:Stream<Stream<String>>
此函数会将他们化为基本数据类型,然后由一个stream统一包裹
排序
排序,需要实现Comparable接口
//sorted() 自然排序,内部还是调用Comparable,stream内部对象必须继承这个接口
//sorted(Compartor com) 自定义排序,Compartor内静态方法接收两个参数,返回两者的差值
str.sorted().forEach(System.out::println);
终止操作
匹配
//allMatch(Predict p) 所有元素都匹配的话就返回true
boolean asdf = str.allMatch(e -> e.getAge()>22);
System.out.println(asdf);
//anyMatch(Predict p) 只要有一个元素匹配的话就返回true
boolean asdf = str.anyMatch(e -> e.getAge()>22);
System.out.println(asdf);
//noneMatch(Predict p) 没有一个匹配的话就返回true
boolean asdf = str.noneMatch(e -> e.getAge()>28);
System.out.println(asdf);
//findFirst() 返回第一个元素,返回值为Optional类型的元素
Optional<People> peo = str.findFirst();
System.out.println(peo);
//findAny() 顺序流只能返回第一个值,并行流可以随机返回一个,基本上不用,没啥用的
Optional<People> o = str.findAny();
System.out.println(o);
查询
//count() 返回stream内数据的个数,返回值类型为long
long a = str.filter(s -> s.getAge()>22).count();
System.out.println(a);
//max(Comparator c), min(Comparator c) 自定义排序
Optional<People> w = str.max((x,y)->Integer.compare(x.getAge(),y.getAge()));
System.out.println(w);
//forEach(Consumer c) 遍历stream内的所有元素,进行一个操作
str.forEach(System.out::println);
归约
//reduce(T identity , BinaryOperator bin) 将流内的数据合成一个
// 初始值,可以理解为基数 || 泛型为<T,T,T> 传进去的两个参数和返回的参数类型一样
int a = str.map(People::getAge).reduce(0,Integer::sum);
System.out.println(a);
//reduce(BinaryOperator)
Optional<Integer> ages = str.map(People::getAge).reduce(Integer::sum);
System.out.println(ages);
收集
就是将stream内的数据收集到一个容器内,list(有序)或者set(无序)
//有序
List<People> peopleList = str.filter(s -> s.getAge() > 3).collect(Collectors.toList());
peopleList.forEach(System.out::println);
//无序
Set<People> peopleSet = str.filter(s -> s.getAge() > 3).collect(Collectors.toSet());
peopleSet.forEach(System.out::println);
Optional类
避免空指针的一个类,可以理解为一个容器,具有泛型。
创建类的对象
//创建带参optional
Optional<People> op = Optional.of(new People());
//创建空的optional
Optional<People> op1 = Optional.empty();
//空不空皆可,内部会自动判断
People pe = new People();
pe = null;
Optional<People> op2 = Optional.ofNullable(pe);
常用方法
Optional<T> op = Optional.of(new T());
//返回optiona内的对象,为空的话就抛异常
op.get()
//返回optiona内的对象,如果为空的话就返回other
op.orElse(T other)
//判断是否包含对象
op.isPresent()