JDK1.8---函数式编程(lambda、方法引用、Stream)

什么是函数式编程?

一切都是数学函数。函数式编程语言里也可以有对象,但通常这些对象都是恒定不变的 —— 要么是函数参数,要什么是函数返回值。函数式编程语言里没有 for/next 循环,因为这些逻辑意味着有状态的改变。相替代的是,这种循环逻辑在函数式编程语言里是通过递归、把函数当成参数传递的方式实现的。

一、lambda表达式

组成:参数列表、箭头符号(->)和函数体
具体展现形式:

  1. 表达式函数(没有return):表达式会被执行然后返回执行结果。
  2. 语句块表达式(每一条路径都要有return):语句块中的语句会被依次执行,就像方法中的语句一样

事例:

package com.example.demo;

import org.junit.Test;

/**
 * @Author helloc
 * @Date 2020/4/14 11:15
 * @Version 1.0
 */
public class Lambda {
    @Test
    public void test(){
   		//用lambda新建线程,线程内部只有一条语句
        new Thread(()->System.out.println("i")).start();
    	//用lambda新建线程,线程内部有执行方法
        new Thread(()->{
            for (int i = 0; i <5 ; i++) {
                System.out.println("i");
            }
        }
        ).start();
   		List<String> languages = Arrays.asList("java","scala","python");
        //集合的遍历操作 java 8 前
        System.out.println("java 8 前");
        for(String s: languages){
            System.out.println(s);
        }
        // java 8 lambda
        System.out.println("java 8 lambda");
        languages.forEach(s -> System.out.println(s));
        // java 8 stream lambda
        System.out.println("java 8 stream lambda");
        languages.stream().forEach(s -> System.out.println(s));
    }
}

集合基于1.8后进行流(Stream)操作;
在这里插入图片描述
大概能分成三类:

  1. Intermediate(中间操作,意思就是用完这些方法还可以继续用终端操作)
    map (mapToInt, flatMap 等)、 filter、 distinct、 sorted、 peek、 limit、 skip、 parallel、 sequential、 unordered

  2. Terminal(终端操作)
    forEach、 forEachOrdered、 toArray、 reduce、 collect、 min、 max、 count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

  3. Short-circuiting(短路)
    anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 limit

常见操作如下:

package com.example.demo;

import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author helloc
 * @Date 2020/4/14 11:15
 * @Version 1.0
 */
public class Lambda {
    @Test
    public void test(){
        List<String> languages = Arrays.asList("java","scala","python");
        //对象数组取一个字段组成a,b,c  结果 java,scala,python
        languages.stream().map(x->x).collect(Collectors.joining(","));
        //1.map/flatMap    
        //map的作用就是把 inputStream 的每一个元素,映射成 outputStream 的另外一个元素 flatmap则代表一对多
        //将list中每个字符都变成大写 
        languages.stream().map(String::toUpperCase).collect(Collectors.toList());
              //结果:JAVA SCALA PYTHON
              
        //将list中每个字符都追加一个1 
        languages.stream().map(n->n+'1').collect(Collectors.toList());
              //结果:java1 scala1 python1
              
        // flatMap 把多个集合的值都放进流中最后去转换成一个集合
        Stream<List<Integer>> inputStream = Stream.of(Arrays.asList(1),Arrays.asList(2, 3),Arrays.asList(4, 5, 6));
        Stream<Integer> outputStream = inputStream.
                flatMap((childList) -> childList.stream());
        List<Integer> num=outputStream.collect(Collectors.toList());
        num.forEach(x->System.out.println(x));
              //结果:1 2 3 4 5 6
              
        //2.filter 过滤  筛选出来长度大于4的集合
        languages=languages.stream().filter(x->x.length()>4).collect(Collectors.toList());
              //结果:languages为 {"scala","python"}
              
        //3.forEach forEach 和常规 for 循环的差异不涉及到性能,它们仅仅是函数式风格与传统 Java 风格的差别。
        languages.stream().filter(x->x.length()>4).forEach(s->System.out.println("1:"+s));
        	 //结果:1:scala 1:python
        	 
        //4.peek 对每个元素操作并返回一个新的stream  然后之后操作都在这个新的stream上操作
        languages.stream().filter(x->x.length()>4).peek(x->System.out.println(x)).map(String::toUpperCase).collect(Collectors.toList());
             //结果:scala python SCALA  PYTHON
        //5.findFirst 用来判断空指针 因为集合为string 把list第一个元素拿出来用map output转换为int,集合为null则返回-1
        languages.stream().findFirst().map(String::length).orElse(-1);
        //打印集合中第一个元素,如果集合为空则打印false
        languages.stream().findFirst().orElse("false");
        //判断字符串是否为空字符串
        String str="xxx";
        int s= Optional.ofNullable(str).map(String::length).orElse(-1);
        
        //reduce 主要作用是把 Stream 元素组合起来  reduce(初始位,BinaryOperator操作) 所谓初始位 结果=初始位+BinaryOperator得到的值
        //合并所有元素  结果x=""+javascalapython  
        String x=languages.stream().reduce("",String::concat);
        // 求最小值,minValue = -3.0  从10.0到-3.0 获取最小
        double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(10.0, Double::min);
		// 求和,sumValue = 10, 有起始值 0+ 10=10
        int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
		// 求和,sumValue = 10, 无起始值  由于没有初始值 所以得到的是option 所以用get()
        sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
        
        //limit/skip limit返回前n个元素 skip则扔掉前n个元素  结果为scala
        languages.stream().skip(1).limit(1).collect(Collectors.toList());
        
        //sorted  排序 结果:javapythonscala
        languages= languages.stream().sorted((a,b)-> a.compareTo(b)).collect(Collectors.toList());
        //match  
        //allMatch:Stream 中全部元素符合传入的 predicate,返回 true  结果true
        boolean s=languages.stream().allMatch(x->x.length()>2);
        //anyMatch:Stream 中只要有一个元素符合传入的 predicate,返回 true 结果true
        boolean s=languages.stream().allMatch(x->x.equal("scala"));
        //noneMatch:Stream 中没有一个元素符合传入的 predicate,返回 true   结果true
         boolean s=languages.stream().allMatch(x->x.equal("xxxx"));
    }
}

总之,Stream 的特性可以归纳为:

  • 不是数据结构
  • 它没有内部存储,它只是用操作管道从 source(数据结构、数组、generator function、IO channel)抓取数据。
  • 它也绝不修改自己所封装的底层数据结构的数据。例如 Stream 的 filter 操作会产生一个不包含被过滤元素的新 Stream,而不是- - 从 source 删除那些元素。
  • 所有 Stream 的操作必须以 lambda 表达式为参数
  • 不支持索引访问
  • 你可以请求第一个元素,但无法请求第二个,第三个,或最后一个。不过请参阅下一项。
  • 很容易生成数组或者 List
  • 惰性化
  • 很多 Stream 操作是向后延迟的,一直到它弄清楚了最后需要多少数据才会开始。
  • Intermediate 操作永远是惰性化的。
  • 并行能力
  • 当一个 Stream 是并行化的,就不需要再写多线程代码,所有对它的操作会自动并行进行的。
  • 可以是无限的
  • 集合有固定大小,Stream 则不必。limit(n) 和 findFirst() 这类的 short-circuiting 操作可以对无限的 Stream 进行运算并很快完成。

二、方法引用

类型示例代码示例对应的Lambda表达式
引用静态方法ContainingClass::staticMethodNameString::valueOf(s) -> String.valueOf(s)
引用某个对象的实例方法containingObject::instanceMethodNamex::toString()() -> this.toString()
引用某个类型的任意对象的实例方法ContainingType::methodNameString::toString(s) -> s.toString
引用构造方法ClassName::new String::new() -> new String()
package com.example.demo;

import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author helloc
 * @Date 2020/4/14 11:15
 * @Version 1.0
 */
public class Lambda {
    @Test
    public void test(){
      List<String> languages = Arrays.asList("scala","java","python");
      //方法引用
      languages= languages.stream().sorted(String::compareTo).collect(Collectors.toList());
      //普通lambda
      languages= languages.stream().sorted((a,b)->a.compareTo(b)).collect(Collectors.toList());
      languages.stream().forEach(System.out::println);
      
    }
}

lambda两个集合操作

package com.ymdd.galaxy.appmanage.core.appauth.service;
 
import java.util.ArrayList;
import java.util.List;
import static java.util.stream.Collectors.toList;
 
 
public class Test {
 
    public static void main(String[] args) {
        List<String> list1 = new ArrayList<String>();
        list1.add("1");
		list1.add("2");
		list1.add("3");
		list1.add("5");
		list1.add("6");
 
        List<String> list2 = new ArrayList<String>();
        list2.add("2");
		list2.add("3");
		list2.add("7");
		list2.add("8");
 
        // 交集
        List<String> intersection = list1.stream().filter(item -> list2.contains(item)).collect(toList());
        System.out.println("---交集 intersection---");
        intersection.parallelStream().forEach(System.out :: println);
 
        // 差集 (list1 - list2)
        List<String> reduce1 = list1.stream().filter(item -> !list2.contains(item)).collect(toList());
        System.out.println("---差集 reduce1 (list1 - list2)---");
        reduce1.parallelStream().forEach(System.out :: println);
 
        // 差集 (list2 - list1)
        List<String> reduce2 = list2.stream().filter(item -> !list1.contains(item)).collect(toList());
        System.out.println("---差集 reduce2 (list2 - list1)---");
        reduce2.parallelStream().forEach(System.out :: println);
 
        // 并集
        List<String> listAll = list1.parallelStream().collect(toList());
        List<String> listAll2 = list2.parallelStream().collect(toList());
        listAll.addAll(listAll2);
        System.out.println("---并集 listAll---");
        listAll.parallelStream().forEachOrdered(System.out :: println);
 
        // 去重并集
        List<String> listAllDistinct = listAll.stream().distinct().collect(toList());
        System.out.println("---得到去重并集 listAllDistinct---");
        listAllDistinct.parallelStream().forEachOrdered(System.out :: println);
 
        System.out.println("---原来的List1---");
        list1.parallelStream().forEachOrdered(System.out :: println);
        System.out.println("---原来的List2---");
        list2.parallelStream().forEachOrdered(System.out :: println);
 
    }
}
  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值