3/19day14_ Lambda_Stream

2020-03-19  本文已影响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表达式

函数式编程思想

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

冗余的Runnable代码

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

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

Lambda的标准格式

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

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

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

Lambda的参数和返回值

Lambda的省略格式

 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流”其实是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值)。

获取流方式

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

获取流的代码演示

 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流的常用方法

    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));

    }
        Stream<String> s1 = Stream.of("java", "php", "C", "Go");
        //count统计个数方法
        long count = s1.count();
        System.out.println(count);
        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());
        Stream<String> s1 = Stream.of("java", "php", "C", "Go");
        
        //limit 取前几个方法
        Stream<String> limit = s1.limit(3);
        limit.forEach(s -> System.out.println(s));
        Stream<String> s1 = Stream.of("java", "php", "C", "Go");
        //skip 跳过前几个方法
        Stream<String> skip = s1.skip(2);
        skip.forEach(s -> System.out.println(s));
        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));
        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流分为两类

收集Stream流的结果

```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());
    }
    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));
    }

今日小结

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.综合案例(处理两个集合数据) 【重点多练几遍】
上一篇 下一篇

猜你喜欢

热点阅读