美文网首页
3/19day14_ Lambda_Stream

3/19day14_ Lambda_Stream

作者: 蹦蹦跶跶的起床啊 | 来源:发表于2020-03-19 21:47 被阅读0次

复习

1.线程池
    a.创建
        ExecutorService service = Executors.newFixedThreadPool(int 个数);
    b.使用
        service.submit(Runnable r);
        Future<T> future = service.submit(Callable<T> c);
        T result = future.get();//可能会阻塞,直到线程任务执行完毕真的返回结果
2.死锁(了解)
    a.多把锁
    b.多个线程
    c.锁的嵌套(反向嵌套)
3.线程六种状态
    NEW-->RUNNABLE
    BLOCKED-->RUNNABLE
    RUNNABLE-->TERMINATED
    TIMED_WAITING-->RUNNABLE
    WAITING--BLOCKED-->RUNNABLE
4.Timer
    四种任务
    public void schedule(TimerTask task,long delay)
    public void schedule(TimerTask task,long delay,long period);

    public void schedule(TimerTask task,Date date)
    public void schedule(TimerTask task,Date firstDate,long period);
今日:
    2020年3月19日 10:10:10
    Date d = new Date(120,2,19,10,10,10);

今日内容

  • Lambda表达式(函数式编程)
  • Stream流(Lambda的实际运行之一)

Lambda表达式

函数式编程思想

函数就是有输入量、输出量的一套计算方案,也就是“拿什么东西做什么事情”
面向对象过分强调"必须通过对象的形式来做事情". 面向对象注重形式
函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做。做什么,而不是怎么做.

冗余的Runnable代码

new Thread(new Runnable(){run...}) 中, 自己定义的和Runnable一样内容的接口也无法作为参数传递, 因为Thread要求的参数只能是Runnable类型.

本着“一切皆对象”的思想,这种做法是无可厚非的:首先创建一个 Runnable 接口的匿名内部类对象来指定任务内
容,再将其交给一个线程来启动。

Lambda的标准格式

  • 标准格式:
    Lambda省去面向对象的条条框框,格式由3个部分组成:
    1.一些参数
    2.一个箭头
    3.一段代码
    -Lambda表达式的标准格式为:

(参数类型 参数名称) -> { 代码语句;renturn 返回值; }

  • 格式说明
    1.(参数列表)小括号内的语法与传统方法参数列表一致:无参数则留空;多个参数则用逗号分隔。
    2.-> 是新引入的语法格式,代表指向动作,表示拿着前边的参数去做什么事情。
    3.{}大括号内的语法与传统方法体要求基本一致,有返回值, 就return 返回值, 无返回值, 可以省略return。

Runnable 接口的匿名内部类写法可以通过更简单的Lambda表达式达到等效

public class Demo02LambdaRunnable {
    public static void main(String[] args) {
        new Thread(() -> System.out.println("多线程任务执行!")).start(); // 启动线程
    }
}

Lambda的参数和返回值

Lambda的省略格式

  • 参数类型可以省略
  • 如果参数只有一个这种情况下,那么小括号可以省略
  • 如果{ }中的代码可以写成一句代码,那么 { },return关键字和分号可以同时省略(不能只能省略某个,必须三个同时省略).
  • 省略格式代码如下
 Arrays.sort(dogs, ((o1, o2) -> o2.getAge() - o1.getAge()));

Lambda的前提条件

  1. 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。 无论是JDK内置的 Runnable 、Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。
  2. 使用Lambda必须具有上下文推断。 也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才能
    使用Lambda作为该接口的实例。

tips:备注:有且仅有一个抽象方法的接口,称为“函数式接口”。

Stream

传统的集合操作

public class Demo01ForEach {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        for (String name : list) {
            System.out.println(name);
        }
    }  
}

循环遍历的弊端

for循环的语法就是“怎么做”
for循环的循环体才是“做什么”
Lambda让我们可以更加专注于做什么(What),而不是怎么做(How)。
为了解决面向对象语法复杂形式, 引入新的技术: Stream 流式思想
每当我们需要对集合中的元素进行操作的时候,总是需要进行循环、循环、再循环。循环是做事情的方式,而不是目的。另一方面,使用线性循环就意味着只能遍历一次。如果希望再次遍历,只能再使用另一个循环从头开始。

传统集合遍历和Stream流 写法比较

传统写法:

public class TestDemo01 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
        ArrayList<String> zhangs = new ArrayList<>();
        for (String name : list) {
            if (name.startsWith("张")) {
                zhangs.add(name);
            }
        }
        ArrayList<String> three = new ArrayList<>();
        for (String name : zhangs) {
            if (name.length() == 3) {
                three.add(name);
            }
        }
        for (String name : three) {
            System.out.println(name);
        }
    }
}

使用Steam流

public class Demo03StreamFilter {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");
 
        list.stream()
            .filter(s -> s.startsWith("张"))
            .filter(s -> s.length() == 3)
            .forEach(System.out::println);
    }
}

获取流、过滤姓张、过滤长度为3、逐一打印

流式思想


这张图中展示了过滤、映射、跳过、计数等多步操作,这是一种集合元素的处理方案,而方案就是一种“函数模型”。图中的每一个方框都是个“流”,调用指定的方法,可以从一个流模型转换为另一个流模型。而最右侧的数字3是最终结果。
tips:“Stream流”其实是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值)。

获取流方式

要想获取流, 首先要不就是个集合, 要不就是个数组

  • Collection (单列) 集合获取流
    Stream<E> s = 集合对象.stream();

  • Map (双列) 集合获取流
    java.util.Map 接口不是 Collection 的子接口,且其K-V数据结构不符合流元素的单一特征,所以获取对应的流需要分key、value或entry等情况(先获取键或者值的set集合,再用单列集合的获取流方法):
    Stream<E> keys =map.keySet().stream()
    Stream<E> valueStream =map.values().stream();
    Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();

  • 数组获取流
    Stream<String> stream = Stream.of(array);

获取流的代码演示

 public static void main(String[] args) {
        //单列集合
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "1", "2", "3", "544");
        Stream<String> s1 = list.stream();

        //双列集合
        HashMap<String, Integer> map = new HashMap<>();
        map.put("1",22);
        map.put("2",22);
        map.put("3",22);
        Stream<String> s2 = map.keySet().stream();
        Stream<Integer> s3 = map.values().stream();
        Stream<Map.Entry<String, Integer>> s4 = map.entrySet().stream();

        //数组
        Integer[] nums = {10, 20, 30, 40};
        Stream<Integer> nums1 = Stream.of(nums);

    }

Stream流的常用方法

  • 逐一处理方法:forEach()
    public static void main(String[] args) {
        Stream<String> s1 = Stream.of("java", "php", "C", "Go");
       /* s1.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });*/
       //lambda使用
        //s1.forEach((String s) -> {System.out.println(s);});
        //lambda简略格式
        s1.forEach(s -> System.out.println(s));

    }
  • 统计个数:count()方法
        Stream<String> s1 = Stream.of("java", "php", "C", "Go");
        //count统计个数方法
        long count = s1.count();
        System.out.println(count);
  • 过滤方法:filter()方法
        Stream<String> s1 = Stream.of("java", "php", "C", "Go");

        //filte 过滤方法传统写法
/*        Stream<String> stringStream = s1.filter(new Predicate<String>() {
            @Override
            public boolean test(String s) {
                //只想要长度大于3的字符串
                if (s.length() > 3) {
                    return true;
                }
                return false;
            }
        });
                System.out.println(stringStream.count());*/

        //filter的Lambda形式
        Stream<String> stringStream1 = s1.filter(s -> s.length() > 3);
        System.out.println(stringStream1.count());
  • 取前几个:limit()方法
        Stream<String> s1 = Stream.of("java", "php", "C", "Go");
        
        //limit 取前几个方法
        Stream<String> limit = s1.limit(3);
        limit.forEach(s -> System.out.println(s));
  • 跳过前几个: skip()方法
        Stream<String> s1 = Stream.of("java", "php", "C", "Go");
        //skip 跳过前几个方法
        Stream<String> skip = s1.skip(2);
        skip.forEach(s -> System.out.println(s));
  • 映射: map()方法
    如果需要将流中的元素映射到另一个流中,可以使用 map 方法。方法签名:
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);
    该接口需要一个 Function 函数式接口参数,可以将当前流中的T类型数据转换为另一种R类型的流。
        Stream<String> s1 = Stream.of("java", "php", "C", "Go");
        //映射 map()方法
        Stream<Integer> mapStream = s1.map(new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return s.length();
            }
        });
        Stream<Integer> mapStream1 = s1.map((s) -> s.length());
        mapStream.forEach(s -> System.out.println(s));
  • 静态方法合并流: concat()
    如果是两个以上合并,多次进行两两合并即可
    就算不是一种类型, 也可以使用泛型为其父类接收
        Stream<String> s1 = Stream.of("java", "php", "C", "Go");
        Stream<String> s2 = Stream.of("A", "B", "C", "D");

        //合并流方法 concat
        Stream<String> concatStream = Stream.concat(s1, s2);
        concatStream.forEach(s -> System.out.print(s+" "));

总结Stream流分为两类

  • 函数拼接方法: 由于这种方法返回的是流对象,可以进行链式编程
    调用该方法后返回的还是一个流对象
    filter,limit,skip,map,concat
  • 终结方法:由于这类方法返回值不是流, 该流就关闭了, 无法在进行调用其他方法
    调用该方法后,返回值不是流或者无返回值
    forEach,count

收集Stream流的结果

  • 收集到集合中
    调用流的 collect()方法
```java
   public static void main(String[] args) {
        Stream<String> stream = Stream.of("10", "20", "30", "40", "50");
        List<String> list = stream.collect(Collectors.toList());
        Set<String> set = stream.collect(Collectors.toSet());
    }
  • 收集到数组中
    调用流的toArray()方法
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("10", "20", "30", "40", "50");
        Object[] objArray = stream.toArray();
    }

collector 和 collectors

Collector是专门用来作为Stream的collect方法的参数的。而Collectors是作为生产具体Collector的工具类。

注意
一个流只能收集一次
如果收集到数组中,默认收集到Object数组

Stream流的代码演示

    public static void main(String[] args) {
        List<String> one = new ArrayList<>();
        one.add("迪丽热巴");
        one.add("宋远桥");
        one.add("苏星河");
        one.add("老子");
        one.add("庄子");
        one.add("孙子");
        one.add("洪七公");
        List<String> two = new ArrayList<>();
        two.add("古力娜扎");
        two.add("张无忌");
        two.add("张三丰");
        two.add("赵丽颖");
        two.add("张二狗");
        two.add("张天爱");
        two.add("张三");
//        1. 第一个队伍只要名字为3个字的成员姓名;
//        2. 第一个队伍筛选之后只要前3个人;
        Stream<String> s1 = one.stream().filter(s -> s.length() == 3).limit(3);
//        3. 第二个队伍只要姓张的成员姓名;
//        4. 第二个队伍筛选之后不要前2个人;
        Stream<String> s2 = two.stream().filter(s -> s.startsWith("张")).skip(2);
//        5. 将两个队伍合并为一个队伍;
        Stream<String> ss = Stream.concat(s1, s2);
//        6. 根据姓名创建 Person 对象;
        Stream<Person> ps = ss.map(s -> new Person(s));
//        7. 打印整个队伍的Person对象信息。
        ps.forEach(person -> System.out.println(person));
    }

今日小结

  • Stream流处理方式
    Stream.of(1,2,3,4,5).filter().map().forEach()
    如上代码, 是先有元素1 进入filter, 再进入map,再进入forEach结束后,再有元素2, 依次进入

  • Lambda配合函数式接口使用小结, 只要判断函数式接口的参数和返回值能对上, 就可以使用
    Supplier 提供器 () -> 有返回值, 无参
    Consumer 消费器 (x) -> void 有一个参数, 没有返回值
    Function 转换器 (x) ->y , 有一个参数 ,有返回值
    Predicate 判断器 (x) -> boolean, 有一个参数, 返回boolean值
    Comparator 比较器 (a,b)->int , 有两个参数, 返回一个 int值,如果a<b, 返回负数

1.Lambda【重点】
    标准格式: (参数列表)->{方法体;return 返回值;}
    省略格式:
            a.参数的类型可省略
            b.如果只有一个参数,小括号可省略
            c.如果{}中只有一句代码,那么{}和;和return关键字可以同时省略    
    
2.Stream流 【重点】
     a。集合或者数组获取流的方法
                Stream<E> s = 集合.stream();//单列集合
                Stream<E> s = Stream.of(数组/可变参数); //数组获取流
     b.调用流的各种方式
            filter limit skip map count foreach concat
3.综合案例(处理两个集合数据) 【重点多练几遍】

相关文章

  • 3/19day14_ Lambda_Stream

    复习 今日内容 Lambda表达式(函数式编程) Stream流(Lambda的实际运行之一) Lambda表达式...

  • 恶意文件夹

    【%你的iapp在这里哦/恭喜你找到了/3/3/3/3/3/3/3/3/3/3/3/3/3/3/3/3/3/3/3...

  • 3+3+3

    九年了,不曾去过,马路那边的刘家村。唱戏,小路~抓蝌蚪,洗衣服,捞水草,漩涡~种满菜的田地,养着奶牛的茅草屋,充满...

  • 3/3

    郭一博 刘佐千 李文浩 王天聪 柳絮 刘全利 李明东

  • 3/3

  • if(a==3) or if(3==a)

    记得刚写程序那会儿,遇到 if else 的条件判断逻辑,基本都会这样写:if(a==3) 为什么呢? 因为自然...

  • 3/3

    原先我是为了他留长头发,现在他的女朋友剪了短发,他说随她去,都好。 原先她卑微付出真心为他,现在她是个被宠溺的幸福...

  • 3/3

    夜月再至,只剩着静谧和四寂与我作伴, 呼啸而过,耳畔又闻过车马还川流不息, 旧亿渐入,也始终囚于泯然其细枝末节。 ​​​

  • 3:3

    今天是个晴朗的天气。染俄我只想呆在寝室。

  • 美惠教练3  3  3  3

网友评论

      本文标题:3/19day14_ Lambda_Stream

      本文链接:https://www.haomeiwen.com/subject/bwkkyhtx.html