《Java8函数式编程》读书笔记---常用的流操作

240 阅读2分钟

引用值,而不是变量

内部匿名类中,只能使用该方法final类型的变量。但是这一限制在java中不强制,但既成事实上这个变量应该是final的。

但是在java的函数式表达式中,要求变量必须是effectively final。换句话说lambda表达式引用的是值,而不是变量。

 List<Integer> list= Arrays.asList(1,2,4,6,3);
        //old way
        int count=0;
        for (Integer i:
        list){
            if(i<5)
                count++;
        }
        System.out.println(count);

        //lambda way
        long count1=  list.stream()
                        .filter(i -> i<5 )
                        .count();
        System.out.println(count1);

lambda表达式看似更复杂了,对集合做了两次迭代。其实并不是。filter只描述stream,最终不产生新集合,叫做惰性求职方法;而count这样的会从stream产生值的方法叫做及早求值方法。

//惰性求值,在filter中不会打印
        list.stream().filter(i -> {
            System.out.println(i);
            return i<5;
        });

        //及早求值,filter中的打印会输出来
        list.stream().filter(i->{
            System.out.println("j"+i);
            return i<5;
        }).count();

所以理想方式是一系列惰性求值之后,最后用一个及早求值操作。整个过程和建造者模式有共通之处,建造者模式使用一系列造作设置属性和配置,最后build方法真正的创建对象。

常用的流操作


        //collect 及早求值,
        List collected = Stream.of("a","b","c")
                               .collect(Collectors.toList());
        assertEquals(asList("a","b","c"), collected);

        //map 转换成新的流 遍历一遍,map接受一个function接口;
        List collectedMap = Stream.of("a","b","c")
                                  .map(string->string.toUpperCase())
                                  .collect(Collectors.toList());
        assertEquals(asList("A","B","C"), collectedMap);

        //filter模式,filter接受一个predicate接口,返回ture的留下,false的从流中删除
        //filter和map的区别是:map:函数接口的返回值替换原值、filter:函数接口的返回值为true则保留原值,false则删除
        List collectedFilter = Stream.of("a","1b","c")
                .filter(string->string.startsWith("1"))
                .collect(Collectors.toList());
        assertEquals(asList("1b"), collectedFilter);

        //flatMap
        List collectedFlatMap = Stream.of(asList(1,2),asList(3,4))
                .flatMap(numbers -> {
                    System.out.println(numbers);
                    return numbers.stream();
                })
                .collect(Collectors.toList());
        assertEquals(asList(1,2,3,4), collectedFlatMap);

        //max min
        //传入Comparator接口,返回option对象,get()方法可以获得String对象;
        String collectedMax = Stream.of("a","1b","c")
                .max(Comparator.comparing(string->string.length())).get();
        assertEquals("1b", collectedMax);

        //reduce模式
        // max min count ... 遍历stream,累加至accumulator。
        int count= Stream.of(1,2,3)
                .reduce(0,(acc,element)->acc+element);
        assertEquals(6,count);

        //forEach()也是一个及早求值
        List list=new ArrayList();
        Stream.of(1,2,3).forEach(j ->list.add(j));
        System.out.println(list);

:: 用法(方法引用)

方法引用时lambda表达式的一种简单形式,标准语法:Classname::methodName
例子:
artist->artist.getName()
Artist::getName

(name,nationality)->new Artist(name,nationality)
 Artist::new
        //old way
        System.out.println(
                "abEEEcd".chars()
                        .filter(c -> Character.isLowerCase(c))
                        .count()
        );
        //使用::之后更简单
        System.out.println(
                "abEEEcd".chars()
                .filter(Character::isLowerCase)
                .count()
        );

流调试

因为流采用的惰性求值,所以在中间操作时候无法打印中间结果,需要Peek()方法调试。可以在peek方法中打印或者增加断点。示例代码:
``` java
class Person {
String id;
String name;

public Person(String id, String name) {
    this.id = id;
    this.name = name;
}

} public class PeekStream {

public static void main(String[] args) {
    Person p1=new Person("1","jiao1");
    Person p2=new Person("2","jiao2");
    Person p3=new Person("3","3jiao");
    List<Person> list=new ArrayList();
    list.add(p1);
    list.add(p2);
    list.add(p3);
    long c=list.stream()
            .peek(p->
                    System.out.println(p.name))
            .filter(p->p.name.startsWith("j")).peek(
                    p-> System.out.println(p.id))
            .map(p->p.id).count();
    System.out.println();
    System.out.println(c);
}

} ```