了解Java函数式编程

了解Java函数式编程,第1张

了解Java函数式编程

文章目录

一、基本介绍二、Lambda表达式

1、优点2、基本格式3、进一步优化 三、方法引用四、Stream流

1、简介2、准备案例3、创建流 *** 作4、中间 *** 作(过滤、排序、去重、转换等等)

(1)、filter(2)、distinct(3)、map(4)、sorted(5)、limit(6)、skip(7)、flatmap 5、终结 *** 作

(1)、forEach(2)、count(3)、min&max(4)、collect(5)、anyMatch(6)、allMatch(7)、noneMatch(8)、findAny(9)、findFirst(10)、reduce 6、基本数据类型转化优化7、Stream流总结 四、Optional

1、作用2、使用Optional避免空指针异常3、有关Optional

一、基本介绍

"函数式编程"是一种"编程范式"(programming paradigm),也就是如何编写程序的方法论。
它属于"结构化编程"的一种,主要思想是把运算过程尽量写成一系列嵌套的函数调用。

函数式编程优点:

代码简介开发迅速接近自然语言,易于理解易于并发编程 二、Lambda表达式 1、优点

不关注对象是什么,不关注方法名是什么,只关注如何 *** 作数据
可推导可省略
对匿名内部类(是接口且仅有一个抽象方法)进行简化

2、基本格式

(参数列表)->{代码}

例1:

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Lambda表达式学习");
    }
}).start();


new Thread(() -> {
    System.out.println("Lambda表达式学习");
}).start();

例2:

@FunctionalInterface
public interface IntBinaryOperator {

    
    int applyAsInt(int left, int right);
}


 public static int calculateNum(IntBinaryOperator operator) {
        int a = 20;
        int b = 10;
        return operator.applyAsInt(a, b);
}



    int i = calculateNum(new IntBinaryOperator() {
            @Override
            public int applyAsInt(int left, int right) {
                return left + right;
            }
        });

   int i = calculateNum((left, right) -> {
            return left + right;
        });

例3:

 @FunctionalInterface
public interface IntPredicate {

    
    boolean test(int value);
    }
    
    public static void printNum(IntPredicate predicate) {
        int[] arr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        for (int i : arr) {
            if (predicate.test(i)) {
                System.out.println(i);
            }
        }
    }
   

       printNum(new IntPredicate() {
            @Override
            public boolean test(int value) {
                return value % 2 == 0;
            }
        });

     printNum((value)->{
     		return value%2==0;
     });
         
3、进一步优化

参数类型可以省略(上述例子全部省略)方体体只有一句代码时,大括号、return、分号可以省略例如:
如例3 可写为: printNum((value) -> value % 2 == 0);方法体只有一个参数时小括号也可以省略
再改写:printNum(value -> value % 2 == 0); 三、方法引用

lambda表达式再一次改进
基本格式:
类名或对象名::方法名

什么时候用?

我也不太懂 只会alter+enter

例: .mapToInt(author -> author.getAge())
改进:.mapToInt(Author::getAge)

四、Stream流 1、简介

优点:更加简便的 *** 作集合和对象

2、准备案例
@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Author{
    private Long id;
    
    private String name;
    
    private int age;
    
    private List books;

    public Integer getHHH(int age,String name){
        return Integer.valueOf(age+name);
    }
}



@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Book {
    private Long id;
    
    private String title;
    
    private String category;
    
    private double price;
}


    private static List getAuthors() {
        Book book = new Book(1L, "JavaSE", "JAVA", 200);
        Book book1 = new Book(2L, "Python精通", "Python", 205);
        Book book2 = new Book(3L, "JAVAEE", "JAVA", 28);
        Book book3 = new Book(4L, "C++Prime", "C++", 2254);
        Book book4 = new Book(5L, "JAVAWeb", "JAVA,Web", 445);
        Book book5 = new Book(6L, "Redis", "database,Linux", 54);
        Book book6 = new Book(7L, "Mysql", "database", 545);

        List list = new ArrayList<>();
        List list1 = new ArrayList<>();
        List list2 = new ArrayList<>();

        list.add(book);
        list.add(book1);
        list.add(book2);
        list.add(book2);

        list1.add(book3);
        list1.add(book4);

        list2.add(book6);
        list2.add(book6);
        list2.add(book5);

        Author author = new Author(1L, "Mae", 21, list);
        Author author1 = new Author(2L, "Strive", 25, list1);
        Author author2 = new Author(3L, "Naomi", 28, list2);
        Author author3 = new Author(3L, "Naomi", 28, list2);

        return new ArrayList<>(Arrays.asList(author, author1, author2, author3));
    }
3、创建流 *** 作

单列集合:集合对象.stream()

	//例: 
	List authorList=getAuthorList(); 
		authorList.stream();		                        

多列集合:map.entrySet.stream();

 	//例:
 	Map map=new HashMap<>();
 	map.entrySet.stream();

数组:Arrays.stream(数组名)

4、中间 *** 作(过滤、排序、去重、转换等等) (1)、filter

过滤 *** 作
例:输出年龄大于25的作家

       List authors = getAuthors();
        authors.stream()
                .filter(author -> author.getAge()>25)
                .forEach(author -> System.out.println(author));


过滤后只剩下两条

(2)、distinct

去重
案例:打印年龄超过25的作家 并且去重

      List authors = getAuthors();
        authors.stream()
                .filter(author -> author.getAge()>25)
                .distinct()
                .forEach(author -> System.out.println(author));



(3)、map

对流中的元素进行计算或转换(类型)
例:将对象按照年龄转成Integer 然后将年龄加10

        List authors = getAuthors();
        authors.stream()
                .map(author -> author.getAge())
                .distinct()
                .map(age -> age + 10)
                .forEach(age -> System.out.println(age));




(4)、sorted

排序
例:按照年龄降序

        List authors = getAuthors();
        authors.stream()
                .map(author -> author.getAge())
                .distinct()
                .sorted((o1, o2) -> o2-o1)
                .forEach(age -> System.out.println(age));




(5)、limit

限制流的最大长度
案例:打印年龄最大的两个作家(需去重和排序)

   List authors = getAuthors();
        authors.stream()
                .distinct()
                .limit(2)
                .forEach(author -> System.out.println(author));




(6)、skip

跳过所定义长度的流
案例:打印除了最大年龄的所有作家

     List authors = getAuthors();
        authors.stream()
                .distinct()
                .sorted((o1, o2) -> o2.getAge() - o1.getAge())
                .skip(1)
                .forEach(author -> System.out.println(author));




(7)、flatmap

将一个对象转换成多个对象
例 打印所有书籍名字 并去除

     List authors = getAuthors();
        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .forEach(book -> System.out.println(book ));

使用 flatmap 将一个作家集合转换成多个书本集合


例 打印所有书本分类 并去重(注意属于多个分类的书籍)

	    List authors = getAuthors();
        authors.stream()
                .flatMap(author -> author.getBooks().stream())
                .distinct()
                .flatMap(book -> Arrays.stream(book.getCategory().split(",")))
                .distinct()
                .forEach(s -> System.out.println(s));

关键:将属于多个分类的书籍 用逗号分隔转换成数组,然后再用数组的stream()方法 转化成流




5、终结 *** 作

终结 *** 作是stream流中必须的,如果没有终结 *** 作,那么中间 *** 作将不会执行

(1)、forEach

对流中的元素进行遍历
前面的案例都用forEach作为终结 *** 作

(2)、count

获取流中元素个数
例:获取书本个数(去重)

 



(3)、min&max

获取流中元素的最小值和最大值
例:获取年龄最大的作者

 



(4)、collect

把当前流转换成一个集合
案例 转成成set集合 键为作者,值为书名

  List authors = getAuthors();
        Map> map = authors.stream()
                .distinct()
                .collect(Collectors.toMap(author -> author.getName(), author -> author.getBooks()));
        System.out.println(map);


(5)、anyMatch

判断是否有符合匹配条件的元素
例:判断是否有年龄大于25的作家

    List authors = getAuthors();
        boolean b = authors.stream()
                .anyMatch(author -> author.getAge() > 25);


(6)、allMatch

判断所有元素是否都符合条件

(7)、noneMatch

判断是否都不符合条件

(8)、findAny

找到任意一个符合条件的元素

(9)、findFirst

找到第一个符合条件的元素

(10)、reduce

对流中的数据按照指定规则方式计算出一个结果
例 求作者年龄之和(去重)

      List authors = getAuthors();
        Integer sum = authors.stream()
                .distinct()
                .map(author -> author.getAge())
                .reduce(0, (result, age) -> (result + age));
        System.out.println(sum);


6、基本数据类型转化优化

不使用map,而使用mapToInt/Double/Long、flatMapToInt/Double/Long

List authors = getAuthors();
    authors.stream()
            .mapToInt(author -> author.getAge())
            .forEach(value -> System.out.println(value));
7、Stream流总结

流是惰性求值,即不进行终结 *** 作,中间 *** 作也不会执行流是一次性的,对一个集合创建了流,不能再对其进行第二次创流不影响原数据 四、Optional 1、作用

主要为了避免开发过程中出现空指针异常
空指针确实很烦
Exception in thread "main" java.lang.NullPointerException

2、使用Optional避免空指针异常

使用ofNullable获取对象(无论是否为空)
使用ifPresent 如果不为空则执行 为空则不会执行

 List authors = getAuthors();
        Optional authorListOptional = Optional.ofNullable(authors);
        authorListOptional.ifPresent(authors1 -> System.out.println(authors1));
3、有关Optional

Optional中还有许多方法与Stream流中类似

不演示了

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5721437.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-18

发表评论

登录后才能评论

评论列表(0条)

保存