四.java8四大核心函数式接口
1.简介
1.Comsumer
消费类型接口
void accept(T t)
直接消费类型
2.Supplier
供给型接口
T get();
直接获取T类型
3.Function<T, R>
函数型接口
R apply(T t);
就是传入一个t类型的参数然后应用到R类型
4.Predicate
断言型接口
boolean test(T t)
传日一个t类型的数据进行测试
还有一些子类,可以传递多个参数,具体见参考文档。
2.代码测试
public static void main(String[] args) {
FuorFunction function = new FuorFunction();
function.test4();
}
public void test() {
getNumList(10, () -> (int)(Math.random() * 100)).forEach(System.out::println);
}
//测试Supplier函数接口
public List<Integer> getNumList(int num, Supplier<Integer> sup) {
List<Integer> list = new ArrayList<>();
for(int i = 0; i < num; i++) {
list.add(sup.get());
}
return list;
}
//测试Function接口
public void test2() {
String s = "fdad, FDADS";
strHander(s, (x) ->x.substring(0,5));
}
public void strHander(String s, Function<String, String>fun) {
System.out.println(fun.apply(s));
}
//测试Costumer接口
public void test3() {
testCuns(10000.0, (x) -> System.out.println("这次消费为:" + x + "元"));
}
public void testCuns(double money,Consumer<Double>con) {
con.accept(money);
}
//将满足条件的字符串,放入集合中
public List<String> filterStr(List<String> ss, Predicate<String>pre) {
List<String> strlist = new ArrayList<>();
for(String str : ss) {
System.out.println(str.length());
if(pre.test(str)) {
strlist.add(str);
}
}
return strlist;
}
public void test4() {
String []ss = {"中国", "必反" , "中大", "fdae"};
List<String>t = Arrays.asList(ss);
List<String>list = filterStr(t, (s) -> s.length() > 3);
for(String tmp : list) {
System.out.println(tmp);
}
}
五.方法引用
(1)对象::实例方法名字
(2)类::静态方法名字
(3)类::实例方法名字
3.注意事项:
(1)lambda体中的参数列表与返回类型,与函数式接口中抽象方法的函数列表和返回类型值保持一致
(2)若参数列表中第一参数是实例方法的调用者,第二参数是实例方法的参数时,可以ClassName::method;
(3)需要调用构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致。
4.
//类::实例方法名字
public void test4(){
BiPredicate<String, String>bp(x, y) -> x.equal(y);
//第一个参数是实例方法的调用者,第二个参数是调用方法的参数
BiPredicate<String, String>bom = String :: equal();
}
六.中间操作
1.中间操作的特点:
没有终止操作,中间操作不会执行,这就是惰性求值。
2.分类
(1)筛选与切片
常用的方法有
-
- filter(断言型接口 Predicate)
- 根据接口函数的实现进行过滤
-
- limit (n)
- 相当于数据库中的limit,选中前n个
-
- skip (n)
- 相当于数据库中的skip,跳过前n个
-
- distinct
- 去重
(2)映射
-
- map (函数式接口 Function)
- 相当于数据库中的select name ,具体的将某一属性提取出来
-
- flatmap(函数式接口 Function)
- 相当于集合的并集操作,将集合中的集合变得扁平。
(3)排序
-
- sorted()
- 自然排序,按照comparable 按照系统默认
- 定制排序 comparator ,自己实现的比较器排序
示例:
先用Employee实现Comparable接口
//使用年龄进行默认排序
@Override
public int compareTo(Object o) {
if(this.age > ((Employee)o).getAge())return 1;
else if(this.age < ((Employee) o).getAge())return -1;
else return 0;
}
public void test2(){
//需求:获取当前工四年龄大于32的员工信息
List<Employee>empoyees = Arrays.asList(
new Employee(14, "张三"),
new Employee(37, "李四"),
new Employee(36, "王五"),
new Employee(35, "赵刘")
);
//筛选与切片
//内部迭代,是sreamAPI完成的
//中间操作:不执行任何操作,也就是没有终止操作,过滤不会执行
Stream<Employee> stream = empoyees.stream()
.filter((e) -> e.getAge() > 35);
//终止操作,一次执行全部内容:这就是"惰性求值"
stream.forEach(System.out::println);
//可以短路,一旦发现n条满足的就停止。
System.out.println("大于5000的");
empoyees.stream()
.filter((e) -> e.getSalary() > 5000)
.limit(2)
.forEach(System.out::println);
//跳过和去重(重写hashcode和equals)
System.out.println("大于5000的跳过前两个");
empoyees.stream()
.filter((e) -> e.getSalary() > 5000)
.skip(2)
.distinct()
.forEach(System.out::println);
//排序
//定制排序
System.out.println("定制排序");
empoyees.stream()
.sorted((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary()))
.forEach(System.out::println);
//自然排序
System.out.println("自然排序");
empoyees.stream()
.sorted()
.forEach(System.out::println);
}
七.终止操作
1.特点:一般是consumer接口的调用函数
比如foreach;
2.类型
(1)查找与匹配
- allMatch
- noneMatch
- anyMatch
- findFirst
- count
- max
- min
- findAny
前三个返回的boolean,后边返回Optional
如果找到的值是有可能是空的就返回Optional。
(3)归约与收集
-
- reduce(identity(初值),accumlator(归约器))
- 将流中的所有元素反复结合起来
- map-reduce广泛应用于数据搜索
-
- collect (Collectors.)
- Collectors方便创建常见的收集器实例包括
-
数字操作
- 最大值
- 最小值
- 求和
- 平均值 Collection.avarangeDouble(函数式接口);
- 总数字 Collectors.counting()
-
分组
- Collectors.groupingBy(函数式接口) 返回值是一个Map, map没有stream - partitioningBy
-
分区
插入一个遍历map的方法
for(Map<String, String>entry : map.entrySet{
entry.getKey();
entry.getValue();
}
难一点,慢一点的
for (String key : map.keySet){
key + map.get(key);
}
示例
List<Employee> empoyees = Arrays.asList(
new Employee(14, "张三", Employee.Status.FREE),
new Employee(37, "李四",Employee.Status.FREE),
new Employee(36, "王五",Employee.Status.VOCATION),
new Employee(35, "赵刘",Employee.Status.BUSY)
);
boolean b1 = empoyees.stream()
.allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b1);
System.out.println(empoyees.stream().anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY)));
System.out.println(empoyees.stream().noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY)));
Optional<Employee> op = empoyees.stream()
.sorted((e1,e2) -> Integer.compare(e1.getSalary(), e2.getSalary()))
.findFirst();
Optional<Employee> op2 = empoyees.stream()
.filter((e) -> e.getStatus().equals(Employee.Status.FREE))
.findAny();
Optional<Employee> op3 = empoyees.parallelStream()
.filter((e) -> e.getStatus().equals(Employee.Status.FREE))
.findAny();
System.out.println(op.get());
System.out.println(op2.get());
System.out.println(op3.get());
long count = empoyees.stream()
.filter((e) -> e.getSalary() > 5000)
.count();
System.out.println(count);
Optional<Employee> op5 = empoyees.stream()
.max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(op5.get());
//使用映射提取属性
Optional<Integer> op6 = empoyees.stream()
.map(Employee::getSalary)
.min(Integer::compare);
System.out.println(op6.get());
//reduce归
Integer []nums = {1, 3, 5};
List<Integer> list = Arrays.asList(nums);
Integer sum = list.stream()
.reduce(0, (x, y) -> x + y);
System.out.println(sum);
Optional<Integer> opt1 = empoyees.stream()
.map(Employee::getSalary)
.reduce(Integer::sum);
System.out.println(opt1.get());
/*
*
* collect收集,将流转换成其他形式,接受一个Collector 接口实现,给stream芳芳
* */
List<String> list2 = empoyees.stream()
.map(Employee::getName)
.collect(Collectors.toList());
list2.forEach(System.out::println);
Set<String> set = empoyees.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
set.forEach(System.out::println);
Long count3 = empoyees.stream()
.collect(Collectors.counting());
Double ave = empoyees.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(count3);
System.out.println(ave);
Double sum2 = empoyees.stream()
.collect(Collectors.summingDouble(Employee::getSalary));
//最大值
Optional<Integer>max = empoyees.stream()
.map(Employee::getSalary)
.collect(Collectors.maxBy((e1, e2) -> Integer.compare(e1, e2)));
System.out.println(max.get());
//最小值的人
Optional<Employee>min = empoyees.stream()
.collect(Collectors.minBy((e1, e2) -> Integer.compare(e1.getSalary(), e2.getSalary())));
//怎么只收集名字和状态而不收集list
Map<Employee.Status,List<Employee>>map = empoyees.stream()
.collect(Collectors.groupingBy(Employee::getStatus));
map.entrySet().forEach((x) -> System.out.println(x.getKey() + " :" + x.getValue()));
//多级分组
Map<Employee.Status, Map<String,List<Employee>>>mas = empoyees.stream()
.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
if(((Employee)e).getAge() <= 35) {
return "青年";
}else if(((Employee)e).getAge() <= 50){
return "中年";
}else {
return "老年";
}
})));
System.out.println(mas);
//分区
Map<Boolean, List<Employee>>ex = empoyees.stream()
.collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
System.out.println(ex);
/*
*
*
* */
Optional<Integer> count2 = empoyees.stream()
.map((e) -> 1) //每一个人返回一个1然后计算
.reduce(Integer::sum);
System.out.println(count2.get());
来源:CSDN
作者:**未来I象限**
链接:https://blog.csdn.net/fuzekun/article/details/103179669