基础之Lambda和Stream的邂逅

show me the code and talk to me,作的出来更要说的明白
GitHub项目JavaHouse同步收录
喜欢就点个赞呗! 你的支持是我分享的动力!java

引入

是否有遇到看不懂身边同事代码的状况,是否有被面试官问到 Java 新特性不懂的状况。我掐指一算你大概是遇到的了 Lambda 表达式 和 Stream 流。为了解决上述状况,我特意献上一份关于 Lambda 和 Stream 的指南,以解燃煤之急。git

Lambda

普通调用

首先咱们先看第一个例子。github

@Test
public void test(){
        test1(1);
    }

private void test1(int a){
    System.out.println(a);
}
复制代码

运行Test,输出结果面试

1
复制代码

相信这里你们都很清楚,我不须要多废话!bash

内部类调用

那咱们在来看看第二个例子微信

public interface IPerson {
    void personMethod();
}

private void test2(IPerson person){
        person.personMethod();
    }

@Test
public void test2(){
    test2(new IPerson(){
        @Override
        public void personMethod() {
            System.out.println(1);
        }
    });
}
复制代码

运行Test,输出结果ide

1
复制代码

这里的话我将参变成了一个接口,使用了内部类。你们是否是以为这种形式的代码不容易看清楚,一个参数居然放了这么多东西,真是让人头大啊。因此咱们有了 Lambda 表达式。函数

Lambda 重构

咱们使用 Lambda 表达式重写上面代码。获得下面新代码:spa

public interface IPerson {
    void personMethod();
}

private void test2(IPerson person){
        person.personMethod();
    }

@Test
public void test2(){
    test2(() -> System.out.println(1));
}
复制代码

运行Test,输出结果3d

1
复制代码

这样的代码是否是比使用内部类代码优雅了不少,看起来舒服极了,关键代码也少了。这就是 Lambda 表达式的魅力。

Lambda 调用

好了,通过上面的层层递进的例子,咱们引出了 Lambda 表达式。如今咱们开始了解 Lambda 表达式的语法。

语法:

-> 
复制代码

是的,他的调用语法就是一个箭头。固然这样说的话我也不太信。其实还没说完。

当咱们的方法没有参数的时候,没有返回,他须要保留括号,形式以下:

() -> System.out.println(1);
复制代码

当有一个参数的时候,没有返回,小括号能够去掉,形式以下

a -> System.out.println(a)
复制代码

当有多个参数的时候以及方法里面的语法多余一行的时候,没有返回,,形式以下:

(a, b) -> {
            System.out.println(a);
            System.out.println(b);
        }
复制代码

上面例子都是没有返回的,那么有返回又是怎样的呢?形式以下:

a -> {
            System.out.println(a);
            return a;
        }
复制代码

是的,那就加一下返回啊。

函数式接口

其实上面都是展现若是去调用,不知道大家是否发现后者感受到,他没有方法名就去调用了,是否是接受不了。这是正常状况。由于咱们调用的接口里面这有一个方法,因此咱们只须要一个 ->就能够调用到接口里面方法。

因此咱们若是想本身写一个 Lambda 的话。只须要在接口里面写一个抽象方法便可。举了例子:

public interface IPerson {
    int personMethod(int a);
}
复制代码

固然我建议加一个注解@FunctionalInterface,形式以下:

@FunctionalInterface
public interface IPerson {
    int personMethod(int a);
}
复制代码

这样就是限制接口里面只能有一个抽象方法了。这个就叫函数式接口。当咱们再继续往里面加的话,就会报错了:

其实大多数状况下,咱们不须要本身写函数式接口。由于 Java 已经内置了四种常见的函数式接口。

这四个接口须要通常与 Stream 一块儿使用。

Stream

普通迭代

咱们直接看代码,一个普通的迭代例子

public class StreamTest {
     @Test
    public void test2(){
        List list = Arrays.asList(1, 2, 3, 4, 5);
        int count = 0;
        for (Object o : list){
            count ++;
        }
        System.out.println(count);
    }
}
复制代码

运行Test,输出结果

5
复制代码

在 Java8 以前,咱们统计 list 的大小是上面的形式。

Stream 重构

如今咱们用 Stream 重构上面的代码

public class StreamTest {
    @Test
    public void test3(){
        List list = Arrays.asList(1, 2, 3, 4, 5);
        long count = list.stream().count();
        System.out.println(count);
    }
}
复制代码

运行Test,输出结果

5
复制代码

瞬间感受代码清爽了不少,变得优雅了,关键代码也少了。这就是 Stream 的魅力。

通过上面的例子,咱们能够感受到 Stream 能够代替 for 循环,进行特定操做。注意这里是特定的操做,由于 Stream 接口里面只有只封了几个方法。

collect()

collect() 方法能够将 Stream 变成 List等集合形式。

咱们看一个例子:

public class StreamTest {
    @Test
    public void test4(){
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5,1);
        List<Integer> collect = stream.collect(Collectors.toList());    
    }
}
复制代码

fiter()

fiter() 方法与 Predicate 函数接口一块儿使用。

不想看文字,还有图片

该方法能够过滤出特定元素而且返回原来的类型。举一个例子

public class StreamTest {
    @Test
    public void test5(){
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5,1);
        List<Integer> collect = stream.filter(a -> a > 3).collect(Collectors.toList());
        System.out.println(Arrays.asList(collect));
    }
}
复制代码

运行Test,输出结果

[[4, 5]]
复制代码

map()

map() 方法与 Function 函数接口一块儿使用。

不想看文字,还有图片

该方法能够将原来的集合进行修改,包括返回类型,而后返回一个新的集合。举一个例子

public class StreamTest {
   @Test
    public void test8(){
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5,1);
        List<Integer> collect = stream.map(a -> a = 1).collect(Collectors.toList());
// List<Boolean> collect = stream.map(a -> a == 1).collect(Collectors.toList());
        System.out.println(Arrays.asList(collect));
    }
}
复制代码

运行Test,输出结果

[[1, 1, 1, 1, 1, 1]]
复制代码

咱们能够看到两种状况 Integer -> Integer 以及 Integer -> Boolean

注意咱们不能操做同一个 stream 两次,否则会报错,有兴趣能够试试。

distinct()

该方法意如其字,就是去重。代码以下

public class StreamTest {
    @Test
    public void test7(){
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5,1);
        List<Integer> collect = stream.distinct().collect(Collectors.toList());
        System.out.println(Arrays.asList(collect));
    }
}
复制代码

运行Test,输出结果

[[1, 2, 3, 4, 5]]
复制代码

关注微信公众号,随时移动端阅读

公众号.jpg
相关文章
相关标签/搜索