day14【Lambda表达式、Stream流】 过滤:filter、统计个数:count、逐个forEach、 取前几个:limit、跳过前几个:skip、映射:map、静态方法合并流:concat

day14【Lambda表达式、Stream流】

反馈和复习
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);
今日:
	202031910:10:10
	Date d = new Date(120,2,19,10,10,10);
今日内容
JDK8的新特性
1.Lambda表达式(函数式编程)
2.Stream流(Lambda的实际运行之一)     
今日的内容我们当做加薪的技术去学    

第一章 Lambda表达式

1.1 函数式编程的思想
函数式编程思想: 以一种尽量简单的格式,简化面向对象中复杂的格式,
			  面向对象强调是以何种形式去做,
			  而函数式编程思想强调是拿什么东西做什么事情,而不强调以何种形式去做!
1.2 冗余的Runnable代码
public class TestRunnableDemo {
    public static void main(String[] args) {
        //1.我要使用实现的方式 创建一个线程对象
        new Thread(new Runnable() {
            public void run() {
                System.out.println(Thread.currentThread().getName()+"执行了...");
            }
        }).start();

        //分析: 传统Runnable实现方式的冗余代码
        //a.我们为了避免创建一个新类,不得不(被逼的)去搞一个匿名内部类
        //b.为了迎合面向对象的语法,我们只能(被逼的)使用Runnable的实现类
        //c.重写时方法必须(被逼的)和接口中一模一样
        //d.似乎我们真正需要的其实就是任务代码(心甘情愿写的)
    }
}
1.3 函数式编程Lambda的体验
//体验一下Lambda表达式(函数式编程)优雅的写法
new Thread(()->{System.out.println("执行了...");}).start();
1.4 Lambda标准格式介绍【重点】
Lambda的标准格式:
	(参数列表)->{方法体;return 返回值;}
详情介绍:
	(参数列表) 相当于方法的参数,如果没有参数,那么只写小括号即可(小括号不能省略)
    ->: 固定用法,代码拿着前面的参数,去做什么事情
    {}: 大括号中先写计算过程,如果有返回值return 返回值;,如果没有返回值return语句可以省略    
//面向对象的格式
new Thread(new Runnable() {
	public void run() {
		System.out.println("执行了...");
	}
}).start();   
//Lambda的格式
new Thread(()->{System.out.println("执行了...");}).start();
1.5 Lambda的参数和返回值【重点】
public static void arraySort1(){
    //1.数组
    Integer[] nums = {4,5,61,7,8,9,34,56,345};
    //2.对数组排序(默认升序)
    //Arrays.sort(nums);
    //        Arrays.sort(nums, new Comparator<Integer>() {
    //            @Override
    //            public int compare(Integer o1, Integer o2) {
    //                //降序
    //                return o2-o1;
    //            }
    //        });
    //使用Lambda表达式修改上面冗余的代码
    Arrays.sort(nums,(Integer o1, Integer o2)->{return o2-o1;});

    //3.输出
    System.out.println(Arrays.toString(nums));
}

public static void main(String[] args) {
    //1.数组
    Dog[] dogs = new Dog[4];
    dogs[0] = new Dog(4,"jack",4);
    dogs[1] = new Dog(3,"mary",5);
    dogs[2] = new Dog(2,"ady",6);
    dogs[3] = new Dog(5,"hanmeimei",3);
    //2.排序
    //        Arrays.sort(dogs, new Comparator<Dog>() {
    //            @Override
    //            public int compare(Dog o1, Dog o2) {
    //                //按照狗的年龄降序
    //                return o2.age-o1.age;
    //            }
    //        });
    //使用Lambda表达式修改上面冗余的代码
    Arrays.sort(dogs,(Dog o1, Dog o2)->{return o2.age-o1.age;});

    //3.打印
    for (Dog dog : dogs) {
        System.out.println(dog);
    }
}

1.6 Lambda的省略格式【重点】
a.参数类型可以省略
b.如果参数只有一个,那么小括号可以省略
c.如果{}中的代码可以写成一句代码.那么{},return关键字和分号可以同时省略(不能省略某个)   
    
//体验一下Lambda表达式(函数式编程)优雅的写法
new Thread(()->{System.out.println("执行了...");}).start();
//省略格式
new Thread(()->System.out.println("执行了...")).start();  


//使用Lambda表达式修改上面冗余的代码
Arrays.sort(nums,(Integer o1, Integer o2)->{return o2-o1;});
//省略格式
Arrays.sort(nums,(o1,o2)-> o2-o1);


//使用Lambda表达式修改上面冗余的代码
Arrays.sort(dogs,(Dog o1, Dog o2)->{return o2.age-o1.age;});
//省略格式
Arrays.sort(dogs,(o1,o2)->o2.age-o1.age);
1.7 强烈注意:Lambda的使用前提
a.Lambda只能用于替换 有且仅有一个抽象方法的接口的匿名内部类对象,这种接口称为函数式接口
b.Lambda具有上下文推断的功能, 所以我们才会出现Lambda的省略格式   

第二章 Stream流

2.1 引入:传统的集合操作
public class TestDemo01 {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张强");
        list.add("张三丰");

        //1. 首先筛选所有姓张的人;
        ArrayList<String> zhangs = new ArrayList<String>();
        for (String name : list) {
            if (name.startsWith("张")){
                zhangs.add(name);
            }
        }

        //2. 然后筛选名字有三个字的人;
        ArrayList<String> threes = new ArrayList<String>();
        for (String zhang : zhangs) {
            if (zhang.length() == 3) {
                threes.add(zhang);
            }
        }

        //3. 最后进行对结果进行打印输出。
        for (String three : threes) {
            System.out.println(three);
        }
    }
}

2.2 循环遍历的弊端分析
Lambda注重于做什么,传统的面向对象注重于怎么做??
    
 for (String three : threes) { //这就是传统的面向对象注重怎么做,就是形式
     System.out.println(three);//这里才是我们注重做什么
 }    
为了解决面向对象语法复杂形式,我们引入一种新的技术:Stream 流式思想

2.3 体验Stream的优雅写法
//4.体验一下Stream流的优雅代码
list.stream().filter(s->s.startsWith("张")).filter(s->s.length()==3).forEach(s-> System.out.println(s));

2.4 流式思想的概述

在这里插入图片描述

2.5 两种获取流的方式【重点】
a.Collection集合获取流
    Stream<E> s = 集合对象.stream();

b.Map集合不能直接获取流,但是可以间接获取流
    map.keySet().stream(); 获取map的键流
    map.values().stream(); 获取map的值流
    map.entrySet().stream(); 获取Map的键值对流
    
c.数组获取流
    Stream<数据中元素的类型> s = Stream.of(数据类型... 变量名);
    
public class StreamDemo01 {
    public static void main(String[] args) {
        //获取各种容器的流
        //1.单列集合
        ArrayList<String> arr = new ArrayList<String>();
        //....添加数据
        Stream<String> s1 = arr.stream();

        //2.双列集合
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        Stream<String> keyStream = map.keySet().stream(); //键流
        Stream<Integer> valueStream = map.values().stream();//值流
        Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream();//键值对流
        
        //3.数组
        Integer[] nums = {10,20,30,40};
        Stream<Integer> s2 = Stream.of(nums);
        Stream<Integer> s3 = Stream.of(11,22,33,44);
    }
}

2.6 Stream流中的常用方法【重点】
  • 逐个处理:forEach(代码演示)

    //1.获取到一个流
    Stream<String> s1 = Stream.of("jack", "tom", "rose", "lilei", "jerry");
    //2.foreach 逐一处理
    //使用匿名内部类
    //        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));
    
    
  • b.统计个数:count(代码演示)

    //3.count 统计个数
    long count = s1.count();
    System.out.println("流中有多少个元素:"+count);
    
    
  • 过滤:filter(代码演示)

    //4.filte 过滤方法
    //匿名内部类
    //        Stream<String> s2 = s1.filter(new Predicate<String>() {
    //            @Override
    //            public boolean test(String s) {
    //                //我们只想要 长度大于4的字符串
    //                return s.length() > 4;
    //            }
    //        });
    
    //Lambda
    Stream<String> s2 = s1.filter(s -> s.length() > 4);
    
    System.out.println(s2.count());
    
    
  • 取前几个:limit(代码演示)

    //5.limit 取前几个
    Stream<String> s3 = s1.limit(3);
    s3.forEach(s-> System.out.println(s));
    
    
  • 跳过前几个:skip(代码演示)

    //6.skip 跳过前几个
    Stream<String> s4 = s1.skip(2);
    s4.forEach(s-> System.out.println(s));
    
    
  • 映射方法:map(代码演示)

    map方法是将流中每个元素,经过某种算法,变成另外一个元素
    //7.map 映射
    //        Stream<Integer> s5 = s1.map(new Function<String, Integer>() {
    //            @Override
    //            public Integer apply(String s) {
    //                return s.length();
    //            }
    //        });
    //Lambda改写
    Stream<Integer> s5 = s1.map(s->s.length());
    
    s5.forEach(s-> System.out.println(s));    
    
    
  • 静态方法合并流:concat(代码演示)

    public static Stream<T> concat(Stream<T> s1,Stream<T> s2);
    
    //8.concat 静态方法,合并两个流
    Stream<String> ss1 = Stream.of("jack","rose");
    Stream<String> ss2  = Stream.of("tom","lucy");
    //静态方法
    Stream<String> sss = Stream.concat(ss1,ss2);
    sss.forEach(s-> System.out.println(s));
    
    注意:
    	a.如果是两个以上流的合并,需要多次两两合并
        b.如果两个流的泛型不一致也可以合并,合并之后新流的泛型是他们共同的父类(不知道其父类,写Object)   
    
    
2.7 练习:集合元素的处理(Stream方式)【今天一天的目标就是他】
//使用传统集合遍历方式
public class StreamDemo04 {
    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("张三");
        //按照求操作集合(使用传统的for循环)
//        1. 第一个队伍只要名字为3个字的成员姓名;
        ArrayList<String> one1 = new ArrayList<String>();
        for (String name : one) {
            if (name.length() == 3) {
                one1.add(name);
            }
        }
//        2. 第一个队伍筛选之后只要前3个人;
        ArrayList<String> one2 = new ArrayList<String>();
        for (int i = 0; i < 3; i++) {
            String name = one1.get(i);
            one2.add(name);
        }


//        3. 第二个队伍只要姓张的成员姓名;
        ArrayList<String> two1 = new ArrayList<String>();
        for (String name : two) {
            if (name.startsWith("张")){
                two1.add(name);
            }
        }
//        4. 第二个队伍筛选之后不要前2个人;
        ArrayList<String> two2 = new ArrayList<String>();
        for (int i = 2; i < two1.size(); i++) {
            String name = two1.get(i);
            two2.add(name);
        }

//        5. 将两个队伍合并为一个队伍;
        ArrayList<String> all = new ArrayList<String>();
//        all.addAll(one2);
//        all.addAll(two2);
        for (String name : one2) {
            all.add(name);
        }
        for (String name : two2) {
            all.add(name);
        }

//        6. 根据姓名创建 Person 对象;
        ArrayList<Person> persons = new ArrayList<Person>();
        for (String name : all) {
            Person p = new Person(name);
            persons.add(p);
        }

//        7. 打印整个队伍的Person对象信息。
        for (Person person : persons) {
            System.out.println(person);
        }

    }
}

使用Stream流的方式
public class StreamDemo05 {
    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 对象; string -- person
        Stream<Person> ps = ss.map(s -> new Person(s));

//        7. 打印整个队伍的Person对象信息
        ps.forEach(p-> System.out.println(p));
    }
}
    

2.8 总结:函数拼接和终结方法
函数拼接方法: 由于这种方法返回的还是流对象,故支持链式编程
	调用该方法之后,返回还是一个流对象
	有:filter,limit,skip,map,concat
终结方法: 由于终结方法没有返回或者返回的不是流,那么不支持链式编程,并且当某个流调用终结方法之后,该流就关闭了,不能继续调用其他任何方法
	调用该方法之后,返回值不是流或者无返回值
	有:forEach,count

2.9 收集Stream的结果
可以把流收集到集合中,调用流的collect方法即可
可以把流收集到数组中,调用流的toArray方法即可
public class StreamDemo03 {
    public static void main(String[] args) {
        //收集流中的结果
        Stream<Integer> s1 = Stream.of(1,2,3,4,5);
        //....对流进行各种操作
        //1.将流中的结果收集到集合中
        List<Integer> list = s1.collect(Collectors.toList());
        System.out.println(list);

        Set<Integer> set = s1.collect(Collectors.toSet());
        System.out.println(set);
        //2.将流中的结果收集到数组中
        Object[] objs = s1.toArray();
        for (Object obj : objs) {
            System.out.println(obj);
        }
    }
}
注意:
	a.一个流只能收集一次(第二次收集会报错!!!)
    b.如果收集到数组中某个收集到Object数组    
    

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

发布了23 篇原创文章 · 获赞 0 · 访问量 1138

猜你喜欢

转载自blog.csdn.net/qq_44845814/article/details/104995433