`
gaozzsoft
  • 浏览: 424683 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类

JAVA 8的Lambda表达式和Stream API研究

 
阅读更多

JAVA 8 Lambda表达式简化了代码开发,代码简洁,类似Python。

代码实现例子:

 

new Thread(() -> System.out.println("It's a lambda function!")).start();

 

List<String> languagesList = Arrays.asList("java","scala","python");

languagesList.forEach(x -> System.out.println(x));

languagesList.forEach(System.out::println);

 

 

List<Double> costList = Arrays.asList(10.0, 20.0,30.0);

costList.stream().map(x -> x + x*0.05).forEach(x -> System.out.println(x));

 

 

 

List<Double> costList = Arrays.asList(10.0, 20.0,30.0);

double allCost = costList.stream().map(x -> x+x*0.05).reduce((sum,x) -> sum + x).get();

System.out.println(allCost);

 

 

 

List<Double> costList = Arrays.asList(10.0, 20.0,30.0,40.0);

List<Double> filteredCostList = costList.stream().filter(x -> x > 25.0).collect(Collectors.toList());

filteredCostList.forEach(x -> System.out.println(x));

 

 

 

List<String> languagesList = Arrays.asList("Java","Python","scala","Shell","R");

filterTest(languagesList,x -> x.startsWith("J"));

 

public static void filterTest(List<String> languagesList, Predicate<String> condition) {

  languagesList.stream().filter(x -> condition.test(x)).forEach(x -> System.out.println(x + " "));

}

 

============================================================================

 

通过使用Stream API对集合数据进行操作,就类似于使用 SQL 执行的数据库查询,也可以使用 Stream API 来并行执行操作。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

 

 

List<Integer> list = Arrays.asList(2, 3, 5, 4, 1, 8, 10, 9, 7, 6);

list.stream().filter((e) -> e > 5).forEach(System.out::println);

 

 

使用Stream操作有三个步骤

 

创建 Stream:从一个数据源(如集合、数组)中获取一个流

中间操作:一个或多个中间操作,对数据源的数据进行处理

终止操作:执行中间操作链,并产生结果

 

Java8 中的 Collection 接口被扩展了,提供了两个获取流的方法:

 

default Stream stream() : 返回一个顺序流

default Stream parallelStream() : 返回一个并行流

 

List<String> list = new ArrayList<>();

Stream<String> stream = list.stream(); //获取一个顺序流

Stream<String> parallelStream = list.parallelStream(); //获取一个并行流

 

 

Java8 中的 Arrays 的静态方法 stream() 可以从数组获取流

Integer[] nums = new Integer[8];

Stream<Integer> stream = Arrays.stream(nums);

 

 

由值创建流

 

可以使用静态方法 Stream.of(), 通过显示值创建一个流。它可以接收任意数量的参数

Stream<Integer> stream = Stream.of(1,2,3,4,5);

 

由函数创建流

可以使用静态方法 Stream.iterate() 和Stream.generate(), 创建无限流。

Stream.iterate(1, (x) -> x + 1).forEach(System.out::println);

Stream.generate(() -> Math.random()).forEach(System.out::println);

 

中间操作又分四类

 

筛选

切割

映射

排序

 

filter(Predicate p), 接收Predicate实例,根据该实例的test方法进行筛选,如

 

List<Integer> list = Arrays.asList(2, 3, 5, 4, 1, 8, 10, 9, 7, 6);

    list.stream()

            .filter((e) -> e > 5)

            .forEach(System.out::println);

 

distinct(),这个方法大家应该能看出来就是去重复的,根据流所生成元素的 hashCode() 和 equals() 去除重复元素

 

List<Integer> list = Arrays.asList(1, 2, 3, 4, 4, 4, 5, 6);

    list.stream()

            .distinct()

            .forEach(System.out::println);

 

 

切割

 

切割也有两个方法

 

limit(long maxSize),截断流,使其元素不超过给定数量,跟SQL语句很像

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);

    list.stream()

            .limit(3)

            .forEach(System.out::println);

 

skip(long n) ,返回一个去掉了前 n 个元素的流。若流中元素 

不足 n 个,则返回一个空流。

 

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);

    list.stream()

            .skip(3)

            .forEach(System.out::println);

 

可以看到这个方法刚好跟limit方法互补了,limit去尾,skip去头。

 

映射

 

map(Function f) ,接收一个Function实例,Function的抽象方法apply是接收一个参数然后返回一个值,这个返回值就是映射的结果

 

List<Integer> list = Arrays.asList(1, 2, 3);

    list.stream()

            .map(x -> x*x)

            .forEach(System.out::println);

 

mapToDouble(ToDoubleFunction f),这个函数跟map很像,只不过映射的结果一定是要Double类型

List<Integer> list = Arrays.asList(1, 2, 3);

    list.stream()

            .mapToDouble(x -> x+0.1)

            .forEach(System.out::println);

 

可以发现Integer类型的元素被映射成Double类型了

类似的还有mapToInt(ToIntFunction f)和mapToLong(ToLongFunction f)方法,这里就不去演示了。

 

List<String> list = Arrays.asList("abc", "efg", "xyz");

        list.stream()//

                .flatMap(TestStreamAPI::string2Stream)//

                .forEach(System.out::println);

 

/**

     * 接收一个字符串将其所以的字符添加到list中然后返回stream

     * @param str

     * @return

     */

    public static Stream<Character> string2Stream(String str) {

        List<Character> list = new ArrayList<>();

        char[] charArray = str.toCharArray();

        for (char c : charArray) {

            list.add(c);

        }

        return list.stream();

    }

 

其实这也不难理解,就像上面mapToDouble方法把流中的每个元素映射成一个Double类型的值一样,现在只是映射成一个Stream

 

 

排序

 

sorted(),可以将流中元素按自然顺序排序。

List<String> list = Arrays.asList("d", "a", "c");

    list.stream()

            .sorted()

            .forEach(System.out::println);

 

sorted(Comparator comp),可以将流中元素按比较器顺序排序。

List<String> list = Arrays.asList("d", "a", "c");

    list.stream()

            .sorted((x,y) -> -x.compareTo(y))

            .forEach(System.out::println);

 

终止操作

终止操作会从流的中间操作流水线生成结果。其结果可以是任何不是流的值,例如: List、 Integer,甚至是 void 。

 

其中终止操作又有三类

 

查找与匹配

归约

收集

 

查找与匹配

 

查找与匹配有下面这么多方法,我只演示几个典型的。

 

allMatch(Predicate p) 检查是否匹配所有元素

anyMatch(Predicate p) 检查是否至少匹配一个元素

noneMatch(Predicate p) 检查是否没有匹配所有元素

findFirst() 返回第一个元素

findAny() 返回当前流中的任意元素

count() 返回流中元素总数

max(Comparator c) 返回流中最大值

min(Comparator c) 返回流中最小值

forEach(Consumer c) 内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。相反, Stream API 使用内部迭代)

 

allMatch(Predicate p)例子

List<Integer> list = Arrays.asList(10, 5, 7, 3);

    boolean allMatch = list.stream()//

            .allMatch(x -> x > 2);//是否全部元素都大于2

    System.out.println(allMatch);

 

findFirst()例子

List<Integer> list = Arrays.asList(10, 5, 7, 3);

    Optional<Integer> first = list.stream()//

            .findFirst();

    Integer val = first.get();

    System.out.println(val);//输出10

 

max(Comparator c)例子

List<Integer> list = Arrays.asList(10, 5, 7, 3);

    Optional<Integer> first = list.stream()//

            .min(Integer::compareTo);

    Integer val = first.get();

    System.out.println(val);//输出3

 

归约

 

归约操作有下面两个方法

 

reduce(T iden, BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 T

reduce(BinaryOperator b) 可以将流中元素反复结合起来,得到一个值。返回 Optional

 

reduce(T iden, BinaryOperator b)例子

 

List<Integer> list = Arrays.asList(10, 5, 7, 3);

    Integer result = list.stream()

        .reduce(2, Integer::sum);

    System.out.println(result);//输出27,其实相当于2+10+5+7+3,就是一个累加

 

reduce(BinaryOperator b)例子

List<Integer> list = Arrays.asList(10, 5, 7, 3);

    Optional<Integer> optional = list.stream()

        .reduce(Integer::sum);

    Integer result = optional.get();

    System.out.println(result);//输出25,其实相当于10+5+7+3,就是一个累加

 

收集

 

collect(Collector c) 将流转换为其他形式。接收一个Collector接口的 

实现,用于给流中元素做汇总的方法

 

List<Integer> list = Arrays.asList(10, 5, 7, 3);

    // 将流中元素收集到List中

    List<Integer> resultList = list.stream()

            .collect(Collectors.toList());

 

    // 将流中元素收集到Set中

    Set<Integer> resultSet = list.stream()

            .collect(Collectors.toSet());

 

    System.out.println(resultList);// 输出[10, 5, 7, 3]

    System.out.println(resultSet);// 输出[3, 5, 7, 10]

 

上面的代码分别将流中的元素收集到List和Set中,其实还可以收集到其类型中,如Map、Optional甚至是Integer等。在收集过程中还可以做点其它操作,比如下面例子,至于其它更多的操作大家还是去看API吧

 

List<Integer> list = Arrays.asList(10, 5, 7, 3);

 

    //计算出流中的元素个数

    Long count = list.stream()//

            .collect(Collectors.counting());

    System.out.println(count);//输出4

 

    //计算流中Integer类型数据的总和

    Integer sum = list.stream()//

            .collect(Collectors.summingInt(x -> x));

    System.out.println(sum);//输出25

  

 

Stream延迟执行

上面“中间操作”那节我说到了“惰性求值”这个东西,即Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

 

 List<Person> list = Arrays.asList(//

            new Person("Jason", 18), //

            new Person("Hank", 46), //

            new Person("Alice", 23));

    // 过滤操作,找出age大于20的Person对象,但是没有终止操作

    list.stream()//

            .filter(x -> x.getAge() > 20);

运行这个测试方法,你会发现没有输出任何东西,因为它并没有终止操作,所以中间操作并未执行。下面加多一个终止操作

    List<Person> list = Arrays.asList(//

            new Person("Jason", 18), //

            new Person("Hank", 46), //

            new Person("Alice", 23));

    // 过滤操作,找出age大于20的Person对象,但是没有终止操作

    list.stream()//

            .filter(x -> x.getAge() > 20)//

            .forEach(System.out::println);

 

 

Stream API还提供了并行流,即多线程执行操作。

 

java.util.Collection<E>新添加了两个默认方法

 

default Stream stream() : 返回串行流

default Stream parallelStream() : 返回并行流

可以发现,stream()和parallelStream()方法返回的都是java.util.stream.Stream<E>类型的对象,说明它们在功能的使用上是没差别的。唯一的差别就是单线程和多线程的执行,关于Stream API还不了解的可以去我开头给出的链接那文章看看。下面我就使用一下并行流,对比串行流看看性能上的差距。

 

 

List<Integer> list = new ArrayList<>();

        // 将10000-1存入list中

        for (int i = 10000; i >= 1; i--) {

            list.add(i);

        }

 

list.stream()// 获取串行流

                .sorted()// 按自然排序,即按数字从小到大排序

                .count();// count()是终止操作,有终止操作才会执行中间操作sorted()

 

List<Integer> list = new ArrayList<>();

        // 将10000-1存入list中

        for (int i = 10000; i >= 1; i--) {

            list.add(i);

        }

 

list.parallelStream()// 获取并行流

                .sorted()// 按自然排序,即按数字从小到大排序

                .count();// count()是终止操作,有终止操作才会执行中间操作sorted()

 

from:

http://blog.csdn.net/timheath/article/details/71366448

http://blog.csdn.net/timheath/article/details/71275179

 

 

分享到:
评论

相关推荐

    【Java8】Lambda表达式 和 Stream API 详解笔记.zip

    【Java8】Lambda表达式 和 Stream API 是Java编程语言中的两个重要创新,它们极大地提升了代码的简洁性和可读性,特别是在处理集合数据时。这里我们将深入探讨这两个特性,并结合实际示例来理解它们的工作原理。 ...

    java8 lambda表达式学习总结

    Java 8 的 Lambda 表达式是其最显著的新特性之一,它引入了一种更为简洁、函数式的编程风格。Lambda 表达式使得处理匿名函数变得更加简单,尤其在需要定义短小、无...学习和掌握Lambda表达式是Java 8开发者的必备技能。

    Java 8 lambda表达式

    - **函数式编程**:Java 8引入了`java.util.Function`等接口,以及`Stream API`,允许开发者使用lambda表达式进行函数式编程,如映射、过滤、聚合等操作。 4. **并行处理**:通过`java.util.concurrent.ForkJoin...

    Java8的lambda表达式

    Java8的Stream API是Lambda表达式的一个重要应用场景。Lambda可以与流API结合,进行数据过滤、映射、聚合等操作,如`list.stream().filter(x -&gt; x &gt; 10).forEach(System.out::println)`。 3. **并行流(Parallel ...

    Stream、Lambda表达式练习.doc

    Stream和Lambda表达式实践 在Java中,Stream API是Java 8中引入的一种新的数据处理方式,它可以对集合进行各种操作,如过滤、映射、聚合等。Lambda表达式是Java 8中引入的一种新的函数式编程方式,它可以将函数作为...

    JAVA 8 Lambda表达式-Lambda Expressions.rar

    Java 8 中引入了几个重要的流(Stream)API,与 Lambda 表达式配合使用,可以实现高效且易于理解的集合操作。例如,我们可以使用 `Arrays.stream()` 将数组转换为流,然后通过 `filter()`, `map()`, `reduce()` 等方法...

    java8中的Lambda表达式

    总之,Java 8 的 Lambda 表达式是简化代码、提高代码可读性和灵活性的重要工具。通过将行为作为参数传递,Lambda 表达式使得函数式编程风格在 Java 中得以实现,为开发者提供了更多编写高效、简洁代码的选择。

    Java 8 新特性详细介绍Lambda表达式、Stream API、接口的默认方法

    1. **Lambda表达式**:Lambda表达式是Java 8的核心特性之一,它引入了函数式编程的概念。Lambda允许以更简洁的语法定义匿名函数,无需创建额外的类或方法。这种表达式使得代码更紧凑,减少了样板代码,尤其在处理...

    java lambda 表达式(语言篇和类库篇)

    总的来说,Java Lambda表达式与相关的类库更新,如Stream API和日期时间API,共同提升了Java的编程效率和代码可读性,使得开发者能够以更简洁的方式处理复杂任务,尤其在处理大量数据和并发场景下。理解并熟练运用...

    Java8的Lambda表达式

    Java 8引入了Lambda表达式,这是一种简洁的编写代码的方式,可以将代码块作为参数传递给方法,或者作为赋值给变量的对象。Lambda表达式为Java增加了函数式编程的能力,使代码更加简洁和灵活。在Java 8中,Lambda...

    jdk1.8 Lambda表达式

    Java 8 引入的 Lambda 表达式是 Java 编程语言的重大变革之一,它允许以更简洁的方式表示单方法接口的实现,极大地增强了 Java 语言的表达能力,尤其是结合了函数式接口、Stream API 和其他新特性后。接下来,我们将...

    Jdk 8 lambda 表达式使用示范

    Java 8 是一个重要的版本更新,它引入了许多新特性,其中最引人注目的就是Lambda表达式和Stream API。这两个特性极大地提升了Java处理集合数据的能力,使得代码更加简洁、高效。接下来,我们将深入探讨Lambda表达式...

    Java 1.8 lambda表达式示例源码

    总而言之,Java 1.8的lambda表达式使得代码更简洁、更易读,它与函数式接口和Stream API结合,大大增强了Java在处理数据和执行任务时的灵活性。学习和熟练掌握这些特性,对于提升Java开发效率和代码质量至关重要。

    2_Lambda表达式.zip

    例如,在处理集合数据时,我们可以使用Lambda表达式配合Java 8的Stream API,实现诸如过滤、映射和求和等操作。例如,以下代码展示了如何使用Lambda表达式和`filter()`、`map()`和`reduce()`方法找出一个整数列表中...

    精通lambda表达式: java多核编程

    Stream API是Java 8引入的另一个重要特性,它与Lambda表达式紧密配合,提供了强大的数据处理能力。通过`.parallel()`方法,我们可以将Stream操作转化为并行执行,从而利用多核处理器的计算能力。例如,`list....

    Java8中Lambda表达式使用和Stream API详解

    总结起来,Java8的Lambda表达式和Stream API使得Java的代码更加简洁、可读,同时也提高了性能。Lambda表达式简化了函数式接口的使用,而Stream API则提供了一种声明式的处理数据的方式。通过这两个特性,开发者可以...

    Java8集合 CompletableFuture lambda表达式 新的TimeAPI 和ForkJoin Demo包

    在这个"Java8集合 CompletableFuture lambda表达式 新的TimeAPI 和ForkJoin Demo包"中,我们可以深入探讨以下几个关键知识点: 1. **Lambda表达式**: Lambda表达式是Java 8的一大亮点,它简化了对匿名函数的处理...

Global site tag (gtag.js) - Google Analytics