java8新特性

Lambda 表达式(了解)

作用 : 用来简化匿名内部类
前提 : 函数式接口

题一:调用Collections.sort()方法,通过定值排序比较两个Employee(先按年龄比,年龄相同按姓名比),使用Lambda作为参数传递
分析:
1.定制排序:指自定义比较器|定制排序
自然排序:内部比较器|自然排序
2.先比较年龄,年龄相同才比较姓名

注意: 函数式接口作为形参,lambda表达式作为实参,将行为作为参数传递
sort(List list, Comparator<? super T> c) 将一个list集合,根据指定的规则做升序排序
代码:

   public class Class001_TestLambda {
	public static void main(String[] args) {
		List<Employee> list = Arrays.asList(
				new Employee("bcd",27,9500),
				new Employee("aaa",29,10000),
				new Employee("abc",28,8000),
				new Employee("bc",28,9000)
		);
		System.out.println(list);

	//Collections.sort()
	//Collections.sort(list);
	//sort(List<T> list, Comparator<? super T> c)  将一个list集合,根据指定的规则做升序排序
	Collections.sort(list,(x,y)->{
		if(x.getAge()==y.getAge()){
			return y.getName().compareTo(x.getName());
		}
		return Integer.compare(y.getAge(),x.getAge());
	});

	System.out.println(list);
	
}
}

功能: 能够对一个字符串,进行某种操作,返回结果

public  static String strHandler(String str,MyFunction my){
    return  my.getValue(str);
}

函数式接口(重点)

只有一个必须被重写的抽象方法的接口

方法的形参: 函数式接口
方法的实参 : lambda表达式|方法引用

@FunctionalInterface 注解强制检测是否为函数式接口
java.util.function 包下提供了一系列的函数式接口

四大内置函数式接口:

Consumer<T> 消费性接口
   void accept(T t) 对给定的参数执行此操作。
Function<T,R>函数型接口
   R apply(T t) 将此函数应用于给定的参数。
Supplier<T>供给型接口
  T get() 获取结果。
Predicate<T> 段言型接口
  boolean test(T t) 根据给定的参数计算此谓词。

代码:

public class Class001_FunctionalInterface {
public static void main(String[] args) {
    testConsumer(10000,m-> System.out.println("为主播打赏"+m));
    testConsumer(20000,m-> System.out.println("做了一个全身spa消费了"+m));
    System.out.println(strHandler("   张三",s->s.trim()));
    System.out.println(strHandler(" abc",s->s.toUpperCase().trim()));

    System.out.println(testNumRandom(5,()->(int)(Math.random()*(10-5+1)+5)));
    System.out.println(testNumRandom(5,()->(int)(Math.random()*(20-10+1)+10)));
    System.out.println(testString(List.of("刘亦菲","成龙","貂蝉","刘伯温"),s -> s.length()==3));
}
//对一个集合中的多个字符串进行某种规则的过滤,返回过滤后的结果
public static List<String> testString(List<String> list, Predicate<String> pre){
    //定义一个List集合,存储满足条件的字符串
    List <String> str1=new ArrayList<>();
    //遍历原list集合,拿到每一个字符串进行判定
    for (String s:list){
        //满足条件字符串放入strs集合
        if (pre.test(s)){
            str1.add(s);
        }
    }
    return str1;
}
//功能: 提供指定个数的,指定规则的随机整数
//定义方法: 1)需求  2)参数:  不确定的数据|有可能会改变的数据定义参数列表上    3)返回值: 方法执行完毕是否需要得到一个结果,需要定义返回值   4)方法名 : 见名知意
public static List<Integer> testNumRandom(int num, Supplier<Integer> sup){
    //定义一个List集合,存储生成的随机数
    List <Integer> list=new ArrayList<>();
    //循环num次,每次调用get方法生成一个随机数
    for (int i=1;i<=num;i++){
        list.add(sup.get());
    }
    //返回结果
    return list;
}
//功能: 对一个字符串进行某种行为的操作得到结果
public static String strHandler(String str, Function<String,String>fun){
 return fun.apply(str);
}
//功能: 每天的缴费记录
public  static void testConsumer(double money, Consumer<Double> con){
    con.accept(money);
}
}

方法引用 :: (看得懂,能修改)

简化lambda表达式的
是lambda表达式的另外一种变现形式

前提 :

  当lambda体的实现是通过调用另外一个方法实现的,可以通过方法引用直接引用这个方法,用来简化完整的lambda表达式的结构

语法:

        对象::实例方法
        类名::静态方法
        类名::实例方法

要求:

1.lambda的参数列表与返回值要求能够一一对应lambda体中所引用方法的参数列表与返回值
2.lambda的返回值要求与所引用方法的返回值保持对应一致
   lambda的参数列表如果只有一个参数 : 作为调用所引用的成员方法的对象存在
   lambda的参数列表如果存在多个参数 : 第一个参数作为调用所引用的成员方法的对象存在,lambda的第二个参数开始,一一对应匹配所引用方法的参数列表

构造器引用:

        数据类型::new

代码:

  public class Class002_MethodQuite {
    public static void main(String[] args) {
        test4();
    }

//构造器引用
public static void test4(){
    //1)lambda的参数列表匹配构造器的参数列表,lambda返回值就是所构建的对象--> 构造器引用
    //Supplier<Employee> sup= ()->new Employee();
    Supplier<Employee> sup= Employee::new;
    System.out.println(sup.get());

    //Function<String,Employee> fun = (s)->new Employee(s);
    Function<String,Employee> fun = Employee::new;
    System.out.println(fun.apply("zhangsan"));
}

//类名::实例方法
public static void test3(){
    ///判断 : 1)lambda体的实现是通过调用另外一个方法实现的  ->√ equals  2)lambda的返回值要求与所引用方法的返回值保持对应一致,lambda的参数列表如果存在多个参数 : 第一个参数作为调用成员方法的对象存在,lambda的第二个参数开始,匹配所引用方法的参数列表 ->对
    //BiPredicate<String,String> pre = (x,y) -> x.equals(y);
    BiPredicate<String,String> pre = String::equals;
    System.out.println(pre.test(new String("nihao"),"nihao"));;
}

//类名::静态方法
public static void test2(){
    //Comparator<Integer> com = (x,y) -> x-y;  //不能通过方法引用,因为-是四则运算,不是方法的调用
    //判断 : 1)lambda体的实现是通过调用另外一个方法实现的->√ compare   2)lambda的参数列表与返回值要求能够一一对应lambda体中所引用方法的参数列表与返回值 √
    //Comparator<Integer> com = (x,y) -> Integer.compare(x,y);
    Comparator<Integer> com = Integer::compare;
    System.out.println(com.compare(100,101));;
}

//对象::实例方法
public static void test1(){
    List<Integer> list = List.of(1,2,3,4,5);
    //判断 : 1)lambda体的实现是通过调用另外一个方法实现的->√ println  2)lambda的参数列表与返回值要求能够一一对应lambda体中所引用方法的参数列表与返回值  √
    PrintStream ps = System.out;
    //Consumer con = i -> System.out.println(i);
    //Consumer con = i -> ps.println(i);
    Consumer con = ps::println;

    list.forEach(con);

    list.forEach(ps::println);

    list.forEach(System.out::println);
}
}

Stream流(重点)

    数据的渠道,用来操作由数据源(数组,集合)所产生的元素序列.
    IO : 传输数据
    Stream流 : 操作数据,计算数据
    数组|集合 : 存储数据

特点:

1.Stream流本身不会存储数据
2.Stream不会修改数据源|源对象,每次回返回持有结果的新的流Stream
3.延迟执行|惰性加载 : 当获取终止行为时候,才会执行一系列的中间操作
4.流都是一次性的流,不能重复使用多次,一旦使用过就已经被破坏

步骤:

1.创建Stream
   1)Collection->stream
   2)Arrays->stream(数组)
   3)Stream.of(值列表)
2.一系列流式的中间操作(都会返回一个持有结果的新的流)
3.终止行为

中间操作 :

1.过滤 Stream filter(Predicate<? super T> predicate);
2.去重 distinct()
        比较equals与hashCode()
3.截取 limit(long) 从第一个开始截取几个
4.跳过 skip(long) 跳过前n个
5.排序 sorted() --> 内部比较器
           sorted(Comparator) ->外部比较器
6.映射 map(Function fun) stream操作的每一个数据都所用于参数函数,映射成一个新的结果,最后返回一个持有所有映射后的新的结果的流

代码:

public class Class002_Stream {
public static void main(String[] args) {
    List<Employee> list = Arrays.asList(
            new Employee("bcd",27,9500),
            new Employee("aaa",29,10000),
            new Employee("abc",28,8000),
            new Employee("bc",28,9000),
            new Employee("bc",28,9000),
            new Employee("cde",30,12000)
    );
    //获取Stream
   Stream<Employee> stream =list.stream();
   //中间操作
    //过滤
    stream=stream.filter(e->e.getAge()>=28);
    //流式调用
    stream=stream.distinct().limit(3).skip(1);
    //排序
    //stream=stream.sorted();
    stream = stream.sorted((x,y)->Double.compare(y.getSalary(),x.getSalary()));
   Stream<String> names =stream.map(e->e.getName()).distinct();
    list.stream().map(e->e.getSalary()).distinct().filter(s->s>=10000).sorted().forEach(System.out::println);
    list.stream().map(e-> e.getAge()).distinct().filter(s->s>=28).sorted().forEach(System.out::println);
    //终止行为
    //stream.forEach(System.out::println);
    names.forEach(System.out::println);

}
}

终止行为:

1.遍历  foreach(Consumer)
2.查找与匹配
   allMatch-检查是否匹配所有元素
   anyMatch-检查是否至少匹配一个元素
   noneMatch-检查是否没有匹配所有元素
   findFirst-返回第一个元素
   findAny-返回当前流中的任意元素
   count-返回流中元素的总个数
   max-返回流中最大值
   min-返回流中最小值
3.规约 reduce
   map->reduce
   加工->计算结果
4.收集
   collect()终止行为:

代码:

public class Class003_Stream {
public static void main(String[] args) {
    List<Employee> list = Arrays.asList(
            new Employee("bcd",27,9500),
            new Employee("aaa",29,10000),
            new Employee("abc",28,8000),
            new Employee("bc",28,9000),
            new Employee("bc",28,9000),
            new Employee("cde",30,12000)
    );
    //判断每一个员工是否都>=20岁
  boolean flag=  list.stream().distinct().allMatch(e->e.getAge()>=20);
    System.out.println(flag);
    //查找薪资最高的员工
    //Optional<T> 存储一个数据的容器类型->jdk8新增的容器类型-->帮助避免空指针异常的出现
  Optional<Employee> op= list.stream().sorted((x, y)->Double.compare(y.getSalary(),x.getSalary())).findFirst();
    System.out.println(op);
    //parallelStream() 并行流
    System.out.println( list.stream().parallel().findAny().get());
    System.out.println(list.parallelStream().findAny().get());
    //大于10000的个数
    System.out.println(list.stream().filter(e->e.getSalary()<=10000).count());
    //查找薪资最高的员工
    System.out.println(list.stream().distinct().max((x,y)->Double.compare(x.getSalary(),y.getSalary())));
    //规约
    //找到公司所有员工的薪资,求和
    System.out.println(list.stream().map(Employee::getSalary).reduce((x,y)->x+y));
    //1+2+3+4+5
    Stream<Integer> stream=Stream.of(1,2,3,4,5);
    /*System.out.println(stream.reduce((x,y)->{
        System.out.println("运算过程:x="+x+"y="+y);
        return x+y;
    }).get());
     */
     System.out.println(stream.reduce((x,y)->{
        System.out.println("运算过程:x="+x+"y="+y);
        return x+y;
    }));
    //收集collect
    System.out.println(list.stream().distinct().count());
    //static <T> Collector<T,?,Long> counting() 返回类型为 T的 Collector接受元素,用于计算输入元素的数量。
    System.out.println(list.stream().distinct().collect(Collectors.counting()));
    //平均薪资  static <T> Collector<T,?,Double> averagingDouble(ToDoubleFunction<? super T> mapper) 返回 Collector ,它生成应用于输入元素的双值函数的算术平均值。
    System.out.println(list.stream().distinct().collect(Collectors.averagingDouble(Employee::getSalary)));

    //static <T> Collector<T,?,List<T>> toList() 返回 Collector ,将输入元素累积到新的 List 。
    System.out.println(list.stream().filter(e->e.getAge()>=28).collect(Collectors.toList()));
    //static <T> Collector<T,?,Set<T>> toSet() 返回 Collector ,将输入元素累积到新的 Set 。
    System.out.println(list.stream().filter(e->e.getAge()>=28).collect(Collectors.toSet()));
    //static <T,K,U>
    //Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) 返回 Collector ,它将元素累积到 Map其键和值是将提供的映射函数应用于输入元素的结果。
    System.out.println(list.stream().distinct().collect(Collectors.toMap(Employee::getName,Employee::getSalary)));
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值