龙空技术网

JDK8 ---- 函数式编程

Iliuhu 63

前言:

现在看官们对“jdk18流式编程”大体比较珍视,看官们都需要分析一些“jdk18流式编程”的相关资讯。那么小编在网摘上搜集了一些对于“jdk18流式编程””的相关文章,希望同学们能喜欢,我们快快来学习一下吧!

@Repeatable() ---- 重复注解定义一个重复注解的容器

package com.demo;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotations {    MyAnnotation[] value();}
定义一个可以重复的注解
package com.demo;import java.lang.annotation.Repeatable;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;@Repeatable(MyAnnotations.class)@Retention(RetentionPolicy.RUNTIME)public @interface MyAnnotation {    String value();}
配置多个重复注解
package com.demo;@MyAnnotation("test1")@MyAnnotation("test2")@MyAnnotation("test3")public class AnnoTest {    @MyAnnotation("fun1")    @MyAnnotation("fun2")    public void test01() {    }    /**     * 解析重复注解     * @param args     */    public static void main(String[] args) throws NoSuchMethodException {        // 获取类中标注的重复注解        MyAnnotation[] annotationsByType = AnnoTest.class.getAnnotationsByType(MyAnnotation.class);        for (MyAnnotation myAnnotation : annotationsByType) {            System.out.println("myAnnotation = " + myAnnotation);        }        System.out.println("============================");        // 获取方法上标注的重复注解        MyAnnotation[] annotationsByType1 = AnnoTest.class.getMethod("test01").getAnnotationsByType(MyAnnotation.class);        for (MyAnnotation myAnnotation : annotationsByType1) {            System.out.println("myAnnotation = " + myAnnotation);        }    }}
类型注解TYPE_PARAMETER:表示注解能写在类型参数的声明语句中。类型参数声明如:<T>
package com.demo;import java.lang.annotation.ElementType;import java.lang.annotation.Target;@Target(ElementType.TYPE_PARAMETER)public @interface TypeParam {}
package com.demo;// @TypeParam可以定义在泛型的前面public class TypeDemo <@TypeParam T> {    public <@TypeParam K extends Object> K test01() {        return null;    }}
TYPE_USE:表示注解可以在任何用到类型的地方使用
package com.demo;import java.lang.annotation.ElementType;import java.lang.annotation.Target;@Target(ElementType.TYPE_USE)public @interface NotNull {}
package com.demo;public class TypeUseDemo {    public @NotNull Integer age = 10;    public Integer sum(@NotNull Integer a, @NotNull Integer b) {        return a + b;    }}
Lambda表达式

对匿名内部类进行简化;关注数据的操作;不关注是什么对象。

核心原则

可推导可省略

基本格式

(参数列表) -> {代码}
package com.demo;import java.util.function.IntPredicate;public class LambdaDemo {    public static void main(String[] args) {        printNum((value) -> value%2 == 0);    }    public static void printNum(IntPredicate predicate) {        int[] arr = {1,2,3,4,5,6,7,8,9};        for (int i : arr) {            if (predicate.test(i)) {                System.out.println("i = " + i);            }        }    }}
package com.demo;import java.util.function.Function;public class LambdaDemo {    public static void main(String[] args) {        Integer integer = typeConver(Integer::valueOf);        System.out.println("integer = " + integer);    }    // 方法泛型    public static <R> R typeConver(Function<String, R> function) {        String str = "1235";        R result = function.apply(str);        return result;    }}
package com.demo;import java.util.function.IntConsumer;public class LambdaDemo {    public static void main(String[] args) {        foreachArr(System.out::println);    }    public static void foreachArr(IntConsumer consumer) {        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8};        for (int i : arr) {            consumer.accept(i);        }    }}
省略规则

参数类型可以省略;

方法体只有一句代码时大括号return和唯一一句代码的分号可以省略;

方法只有一个参数时小括号可以省略;

Stream流

对集合或数组进行链状流式的操作。

创建Stream流单列集合

集合对象.stream()

数组

Arrays.stream(数组);

Stream.of();

双列集合

转换成单列集合后再创建Stream流;

package com.demo;import org.junit.Test;import java.util.HashMap;import java.util.Map;import java.util.Set;import java.util.stream.Stream;public class StreamTest {    @Test    public void test() {        // 双列集合        Map<String, Integer> map = new HashMap<>();        map.put("foo", 1);        map.put("bar", 2);        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();        // 创建流        Stream<Map.Entry<String, Integer>> stream = entrySet.stream();    }}
中间操作
package com.demo.entity;import lombok.AllArgsConstructor;import lombok.Data;import lombok.EqualsAndHashCode;import lombok.NoArgsConstructor;import java.util.List;@Data@NoArgsConstructor@AllArgsConstructor@EqualsAndHashCodepublic class Author {    private Long id;    private String name;    private Integer age;    private String intro;    private List<Book> books;}
package com.demo.entity;import lombok.AllArgsConstructor;import lombok.Data;import lombok.EqualsAndHashCode;import lombok.NoArgsConstructor;@Data@NoArgsConstructor@AllArgsConstructor@EqualsAndHashCodepublic class Book {    private Long id;    private String name;    private String category;    private Integer score;    private String intro;}
package com.demo;import com.demo.entity.Author;import com.demo.entity.Book;import java.util.ArrayList;import java.util.Arrays;import java.util.List;public class StreamDemo {    public static List<Author> getAuthors() {        Author author1 = new Author(1L, "mengduo", 33, "John1231",null);        Author author2 = new Author(2L, "yalsuo", 15, "John1232",null);        Author author3 = new Author(3L, "John", 14, "John1233",null);        Author author4 = new Author(3L, "John", 14, "John1233",null);        List<Book> books1 = new ArrayList<>();        List<Book> books2 = new ArrayList<>();        List<Book> books3 = new ArrayList<>();        books1.add(new Book(1L, "Hello world 001","哲学,爱情", 88, "world 001"));        books1.add(new Book(2L, "Hello world 002","个人成长,爱情", 99, "world 002"));        books2.add(new Book(3L, "Hello world 003","哲学", 85, "world 003"));        books2.add(new Book(3L, "Hello world 003","哲学", 85, "world 003"));        books2.add(new Book(4L, "Hello world 004","爱情,个人传记", 56, "world 004"));        books3.add(new Book(5L, "Hello world 005","爱情", 56, "world 005"));        books3.add(new Book(6L, "Hello world 006","个人传记", 100, "world 006"));        books3.add(new Book(6L, "Hello world 006","个人传记", 100, "world 006"));        author1.setBooks(books1);        author2.setBooks(books2);        author3.setBooks(books3);        author4.setBooks(books3);        List<Author> authorList = new ArrayList<>(Arrays.asList(author1, author2, author3, author4));        return authorList;    }}
filter():流中的元素进行条件过滤map():流中的元素进行计算或转换distinct():去除流中的重复元素sorted():流中的元素进行排序

如果调用空参的sorted(),需要流中的元素实现Comparable。

limit():设置流中的最大长度,超出的被抛弃skip():跳过流中的前n个元素,返回剩下的元素flatMap():把一个对象转换成多个对象作为流中的元素

map只能把一个对象转换成另一个对象作为流中的元素。

package com.demo;import com.demo.entity.Author;import com.demo.entity.Book;import org.junit.Test;import java.util.List;import java.util.function.Consumer;import java.util.function.Function;import java.util.stream.Stream;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        authors.stream()      					 // flatMap 一个元素对象转换成多个元素对象                .flatMap(new Function<Author, Stream<Book>>() {                    @Override                    public Stream<Book> apply(Author author) {                        return author.getBooks().stream();                    }                })                .distinct()                .forEach(new Consumer<Book>() {                    @Override                    public void accept(Book book) {                        System.out.println(book.getName());                    }                });    }}
package com.demo;import com.demo.entity.Author;import com.demo.entity.Book;import org.junit.Test;import java.util.Arrays;import java.util.List;import java.util.function.Consumer;import java.util.function.Function;import java.util.stream.Stream;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        authors.stream()                .flatMap(author -> author.getBooks().stream())                .distinct()                .flatMap(new Function<Book, Stream<String>>() {                    @Override                    public Stream<String> apply(Book book) {                        return Arrays.stream(book.getCategory().split(",")); // 数组转换成流                    }                }).distinct()                .forEach(category -> System.out.println(category));    }}
终结操作forEach():流中的元素进行遍历count():获取当前流中的元素个数
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        long count = authors.stream()                .flatMap(author -> author.getBooks().stream())                .distinct()                .count();        System.out.println("当前流中元素的个数 count = " + count);    }}
max()&min():获取流中元素的最值
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.Comparator;import java.util.List;import java.util.Optional;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 分别获取这些作家的所处书籍的最高分和最低分并打印        Optional<Integer> maxScore = authors.stream()                .flatMap(author -> author.getBooks().stream())                .map(book -> book.getScore())                .max(new Comparator<Integer>() {                    @Override                    public int compare(Integer score1, Integer score2) {                        return score1 - score2;                    }                });        System.out.println(maxScore.get());    }}
collect():当前流转换成一个集合List集合
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;import java.util.stream.Collectors;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 转换成list        List<String> nameList = authors.stream()                .map(author -> author.getName())                .collect(Collectors.toList());        System.out.println("nameList = " + nameList);    }}
Set集合
package com.demo;import com.demo.entity.Author;import com.demo.entity.Book;import org.junit.Test;import java.util.List;import java.util.Set;import java.util.stream.Collectors;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 转换成set        Set<Book> bookSet = authors.stream()                .flatMap(author -> author.getBooks().stream())                .collect(Collectors.toSet());    }}
Map集合
package com.demo;import com.demo.entity.Author;import com.demo.entity.Book;import org.junit.Test;import java.util.List;import java.util.Map;import java.util.function.Function;import java.util.stream.Collectors;public class StreamTest {    @Test    public void test() {        // 获取一个Map集合,map的key为作者名,value为List<Book>        List<Author> authors = StreamDemo.getAuthors();        // 转换成Map        Map<String, List<Book>> authorBookMap = authors.stream()                .distinct()                .collect(Collectors.toMap(new Function<Author, String>() {                    @Override                    public String apply(Author author) {                        return author.getName();                    }                }, new Function<Author, List<Book>>() {                    @Override                    public List<Book> apply(Author author) {                        return author.getBooks();                    }                }));    }}
查找与匹配anyMatch():判断是否有任意符合匹配条件的元素
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;import java.util.function.Predicate;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 满足条件的,返回true,否则返回false        boolean flag = authors.stream()                .anyMatch(new Predicate<Author>() {                    @Override                    public boolean test(Author author) {                        return author.getAge() > 29;                    }                });    }}
allMatch():判断是否都符合匹配条件的元素
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 所有都满足条件的,返回true,只要一个不满足就返回false        boolean flag = authors.stream()                .allMatch(author -> author.getAge() >= 18);    }}
noneMatch():判断是否都不符合匹配条件的元素
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 都不满足条件的,返回true,否则返回false        boolean flag = authors.stream()                .noneMatch(author -> author.getAge() >= 100);    }}
findAny():获取任意一个元素
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;import java.util.Optional;import java.util.function.Consumer;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 获取任意一个元素,不一定能获取到第一个元素        Optional<Author> optionalAuthor = authors.stream().filter(author -> author.getAge() > 18).findAny();        optionalAuthor.ifPresent(new Consumer<Author>() {            @Override            public void accept(Author author) {                System.out.println(author.getName());            }        });    }}
findFirst():获取第一个元素
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;import java.util.Optional;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 获取第一个元素        Optional<Author> first = authors.stream()                .sorted((o1, o2) -> o1.getAge() - o2.getAge())                .findFirst();        first.ifPresent(System.out::println);    }}
reduce() --- 归并

对流中的数据按照指定的计算方式计算出一个结果(缩减操作)。

reduce的作用是把stream中的元素组合起来,我们可以先传入一个初始值,它会按照我们的计算方式依次拿流中的元素和初始化值的基础上进行计算,计算结果再和后面的元素计算。

reduce两个参数的内部计算

package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;import java.util.function.BinaryOperator;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 求所有作者年龄的和        Integer ageSum = authors.stream().distinct()                .map(author -> author.getAge())                .reduce(0, new BinaryOperator<Integer>() {                    @Override                    public Integer apply(Integer result, Integer element) {                        return result + element;                    }                });    }}
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;import java.util.function.BinaryOperator;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 求所有作者中年龄的最大值        Integer ageMax = authors.stream()                .map(Author::getAge)                .reduce(Integer.MIN_VALUE, new BinaryOperator<Integer>() {                    @Override                    public Integer apply(Integer result, Integer element) {                        return result < element ? element : result;                    }                });    }}
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;import java.util.function.BinaryOperator;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 求所有作者中年龄的最小值        Integer ageMin = authors.stream()                .map(Author::getAge)                .reduce(Integer.MAX_VALUE, new BinaryOperator<Integer>() {                    @Override                    public Integer apply(Integer result, Integer element) {                        return result > element ? element : result;                    }                });    }}
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.List;import java.util.Optional;import java.util.function.BinaryOperator;public class StreamTest {    @Test    public void test() {        List<Author> authors = StreamDemo.getAuthors();        // 求所有作者中年龄的最小值        Optional<Integer> minOptional = authors.stream()                .map(Author::getAge)                .reduce(new BinaryOperator<Integer>() {                    @Override                    public Integer apply(Integer result, Integer element) {                        return result > element ? element : result;                    }                });                minOptional.ifPresent(System.out::println);    }}
Stream基本数据类型优化

由于基本数据类型存在自动装箱和拆箱,导致效率降低,所以对部分的时间消耗进行优化,Stream流提供了针对基本数据类型的方法。

如:mapToInt,mapToLong,mapToDouble,flatMapToInt,flatMapToDouble等

优化前优化后并行流

当流中有大量元素时,使用并行流可以提高操作的效率。

并行流:把任务分配给多个线程去完成。

串行流并行流parallel()

package com.demo;import org.junit.Test;import java.util.function.Consumer;import java.util.stream.Stream;public class StreamTest {    @Test    public void test() {        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);        Integer sum = stream.parallel()                // peek是中间方法                .peek(new Consumer<Integer>() {                    @Override                    public void accept(Integer num) {                        System.out.println(num + "\t" + Thread.currentThread().getName());                    }                })                .filter(num -> num > 5)                .reduce((result, element) -> result + element)                .get();    }}
parallelStream():获取并行流对象Optional

避免空指针异常。

创建Optional对象ofNullable()

package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.Optional;public class StreamTest {    @Test    public void test() {        // 获取到的Optional对象        Optional<Author> authorOptional = getAuthorOptional();        authorOptional.ifPresent(author -> author.getName());    }    public static Optional<Author> getAuthorOptional() {        Author author = new Author(1L, "John", 33, "Hello World",null);        return Optional.ofNullable(author);    }}
of()empty()
package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.Optional;public class StreamTest {    @Test    public void test() {        // 获取到的Optional对象        Optional<Author> authorOptional = getAuthorOptional();        authorOptional.ifPresent(author -> author.getName());    }    public static Optional<Author> getAuthorOptional() {        Author author = new Author(1L, "John", 33, "Hello World",null);        return author == null ? Optional.empty() : Optional.of(author);    }}
安全消费值ifPresent()

判断数据是否为空,不为空才会执行。

获取值get():Optional内部数据为空,会出现异常安全获取值orElseGet()

数据为空时,设置默认值;不为空时,获取该数据。

package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.Optional;import java.util.function.Supplier;public class StreamTest {    @Test    public void test() {        // 获取到的Optional对象        Optional<Author> authorOptional = getAuthorOptional();        Author author = authorOptional.orElseGet(new Supplier<Author>() {            @Override            public Author get() {                return new Author();            }        });    }    public static Optional<Author> getAuthorOptional() {        Author author = new Author(1L, "John", 33, "Hello World",null);        return author == null ? Optional.empty() : Optional.of(author);    }}
orElseThrow()

数据为空时,传入的参数来创建异常抛出;不为空时,获取该数据。

package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.Optional;import java.util.function.Supplier;public class StreamTest {    @Test    public void test() {        // 获取到的Optional对象        Optional<Author> authorOptional = getAuthorOptional();        try {            Author author = authorOptional.orElseThrow(new Supplier<Throwable>() {                @Override                public Throwable get() {                    return new RuntimeException("数据为null");                }            });        } catch (Throwable e) {            throw new RuntimeException(e);        }    }    public static Optional<Author> getAuthorOptional() {        Author author = new Author(1L, "John", 33, "Hello World",null);        return author == null ? Optional.empty() : Optional.of(author);    }}
过滤 ---- filter()

filter()对数据进行过滤,原本有数据的,但不符合判断,也会变成一个无数据的Optional对象。

package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.Optional;import java.util.function.Predicate;public class StreamTest {    @Test    public void test() {        Optional<Author> authorOptional = getAuthorOptional();        Optional<Author> optionalAuthor = authorOptional.filter(new Predicate<Author>() {            @Override            public boolean test(Author author) {                return author.getAge() > 18;            }        });        optionalAuthor.ifPresent(author -> System.out.println(author.getName()));    }    public static Optional<Author> getAuthorOptional() {        Author author = new Author(1L, "John", 33, "Hello World",null);        return author == null ? Optional.empty() : Optional.of(author);    }}
判断 ---- isPresent()

isPresent()是否存在数据的判断,如果为空返回值为false,如果不为空,返回值为true

package com.demo;import com.demo.entity.Author;import org.junit.Test;import java.util.Optional;public class StreamTest {    @Test    public void test() {        Optional<Author> authorOptional = getAuthorOptional();        // 对数据进行判断        if (authorOptional.isPresent()) {            System.out.println(authorOptional.get().getName());        }    }    public static Optional<Author> getAuthorOptional() {        Author author = new Author(1L, "John", 33, "Hello World",null);        return author == null ? Optional.empty() : Optional.of(author);    }}
map ---- 数据转换

对数据进行转换,转换之后的数据被Optional包装,保证数据使用的安全。

package com.demo;import com.demo.entity.Author;import com.demo.entity.Book;import org.junit.Test;import java.util.List;import java.util.Optional;import java.util.function.Consumer;public class StreamTest {    @Test    public void test() {        Optional<Author> authorOptional = getAuthorOptional();        Optional<List<Book>> booksOptional = authorOptional.map(author -> author.getBooks());        booksOptional.ifPresent(new Consumer<List<Book>>() {                    @Override                    public void accept(List<Book> books) {                        System.out.println("books = " + books);                    }                });    }    public static Optional<Author> getAuthorOptional() {        Author author = new Author(1L, "John", 33, "Hello World",null);        return author == null ? Optional.empty() : Optional.of(author);    }}
函数式接口

只有一个抽象方法的接口。

Consumer() ---- 消费型接口

# 传入参数进行消费@FunctionalInterfacepublic interface Consumer<T> {	void accept(T t);}
Function() ---- 计算转换型接口
# 传入参数计算或转换,有结果返回@FunctionalInterfacepublic interface Function<T, R> {	R apply(T t);}
Predicate() ---- 判断接口
# 传入的参数条件判断,返回结果为boolean@FunctionalInterfacepublic interface Predicate<T> {	boolean test(T t);}
Supplier() ---- 生产型接口
# 创建对象,把创建好的对象返回@FunctionalInterfacepublic interface Supplier<T> {	T get();}
常用的默认方法and():拼接,&&or():拼接,||negate():取反,!方法引用

简化Lambda表达式。

基本格式

类名或者对象名::方法名

静态方法

类名::方法名

前提:

只有一行代码;并且这行代码调用了某个类的静态方法;抽象方法中所有的参数都按照顺序传入了这个静态方法中。

对象的实例方法

对象名::方法名

前提:

只有一行代码;调用了某个对象的成员方法;抽象方法中所有的参数都按顺序传入到这个成员方法中。

类的实例方法

类名::方法名

前提:

只有一行代码;调用了第一个参数的成员方法;抽象方法中剩余的所有参数都按顺序传入到这个成员方法中。

构造器引用

类名::new

前提:

只有一行代码;调用了某个类的构造方法;抽象方法中的所有参数都按顺序传入到这个构造方法中。

标签: #jdk18流式编程