《Java-SE-第三十三章》之函数式编程

前言

在你立足处深挖下去,就会有泉水涌出!别管蒙昧者们叫嚷:“下边永远是地狱!”

博客主页:KC老衲爱尼姑的博客主页

博主的github,平常所写代码皆在于此

共勉:talk is cheap, show me the code

作者是爪哇岛的新手,水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!


文章目录

  • 函数式编程
    • 概念
    • 函数式接口
      • 常见的函数式接口
    • Lambda表达式
      • 概述
        • 示例一
        • 示例二
        • 示例三
        • 示例四
        • 示例五
          • Lambda省略规则
    • Stream流
      • 常规操作
        • 1. 创建流
          • (1)单列集合:集合对象.stream()
          • (2)数组:Arrays.stream(数组)或者使用Stream.of()来创建
          • (3)双列集合:双列集合无法直接转成流必须转成单列集合在创建流
        • 2. 中间操作
          • filter
          • map
          • distinct
          • sorted
          • limit
          • skip
          • flatMap
          • concat
          • forEach
          • count
          • max&min
          • collect
        • 3. 查找与匹配
            • anyMatch
            • allMatch
            • noneMatch
            • findFirst
            • reduce
        • 4. 函数式接口中默认方法
          • 1. and
          • 2. or
          • 3. negate
      • 注意事项
    • 高级用法
        • 流元素类型转换
        • 并行流


函数式编程

概念

 面向对象是需要关注用什么对象去解决什么问头。而函数式编程,“它是一种使用函数进行编程的方式”,它关注是数据进行了什么操作。

函数式接口

 要了解Lambda表达式,首先需要了解什么是函数式接口,函数式接口定义:一个接口有且只有一个抽象方法 。

注意:

  1. 如果一个接口只有一个抽象方法,那么该接口就是一个函数式接口

  2. 如果我们在某个接口上声明了 @FunctionalInterface 注解,那么编译器就会按照函数式接口的定义来要求该接口,这样如果有两个抽象方法,程序编译就会报错的。所以,从某种意义上来说,只要你保证你的接口中只有一个抽象方法,你可以不加这个注解。加上就会自动进行检测的。

常见的函数式接口

  • ​ Consumer 消费接口

    根据其中抽象方法的参数列表和返回值类型知道,我们可以在方法中对传入的参数进行消费。

在这里插入图片描述

  • ​ Function 计算转换接口

    根据其中抽象方法的参数列表和返回值类型知道,我们可以在方法中对传入的参数计算或转换,把结果返回

在这里插入图片描述

  • ​ Predicate 判断接口

    根据其中抽象方法的参数列表和返回值类型知道,我们可以在方法中对传入的参数条件判断,返回判断结果

    在这里插入图片描述

  • ​ Supplier 生产型接口

    根据其中抽象方法的参数列表和返回值类型知道,我们可以在方法中创建对象,把创建好的对象返回

在这里插入图片描述

Lambda表达式

概述

 Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。 Lambda 表达式(Lambda expression,基于数学中的λ演算得名,也可称为闭包(Closure) 。

Lambda表达式的语法

基本语法: (parameters) -> expression(parameters) ->{ statements; }

Lambda表达式由三部分组成:

  1. paramaters:类似方法中的形参列表,这里的参数是函数式接口里的参数。这里的参数类型可以明确的声明也可不声明而由JVM隐含的推断。另外当只有一个推断类型时可以省略掉圆括号。

  2. ->:可理解为“被用于”的意思

  3. 方法体:可以是表达式也可以代码块,是函数式接口里方法的实现。代码块可返回一个值或者什么都不反回,这里的代码块块等同于方法的方法体。如果是表达式,也可以返回一个值或者什么都不反回。

Lambda基本使用

示例一

我们使用匿名内部类的方式创建并启动线程:

public class Demo {public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {System.out.println("Hello World");}}).start();}
}

可以使用Lambda的格式对其进行修改。修改后如下

public class Demo {public static void main(String[] args) {new Thread(() -> System.out.println("Hello World")).start();}
}

可以简化的匿名内部类必须是函数式接口,函数式接口就是被@FunctionalInterface修饰的接口,同时该接口只有一个抽象方法。

示例二

使用IntBinaryOperator接口计算两个数的和,还是先试用匿名内部类的方式

import java.util.function.IntBinaryOperator;public class Demo2 {public static int calculateNum(IntBinaryOperator operator){int a = 10;int b = 20;return operator.applyAsInt(a, b);}public static void main(String[] args) {int i = calculateNum(new IntBinaryOperator() {@Overridepublic int applyAsInt(int left, int right) {return left + right;}});System.out.println(i);//30}
}

Lambda写法:

public class Demo2 {public static int calculateNum(IntBinaryOperator operator){int a = 10;int b = 20;return operator.applyAsInt(a, b);}public static void main(String[] args) {int i = calculateNum((left, right) -> left + right);System.out.println(i);}
}

示例三

使用IntPredicate接口判读数字是否是偶数,先使用匿名内部类的写法调用该方法。


import java.util.function.IntPredicate;public class Demo3 {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);//是的话直接打印}}}public static void main(String[] args) {//允许你定义并传递一个接受整数参数并返回布尔值的函数IntPredicateprintNum(new IntPredicate() {@Overridepublic boolean test(int value) {return value%2==0;}});}
}

Lambda写法:


import java.util.function.IntPredicate;public class Demo3 {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);//是的话直接打印}}}public static void main(String[] args) {//允许你定义并传递一个接受整数参数并返回布尔值的函数IntPredicateprintNum(value -> value%2==0);}
}

示例四

使用Function接口将字符串转成成Integer类型,IntConsumer,先使用匿名内部类的写法调用该方法。

import java.util.function.Function;public class Demo4 {public static <R> R typeConver(Function<String,R> function){String str = "1235";R result = function.apply(str);return result;}public static void main(String[] args) {Integer result = typeConver(new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return Integer.valueOf(s);}});System.out.println(result);}
}

Lambda写法:

import java.util.function.Function;public class Demo4 {//Function用于表示一个接受一个参数并返回一个结果的函数public static <R> R typeConver(Function<String,R> function){String str = "1235";R result = function.apply(str);return result;}public static void main(String[] args) {Integer result = typeConver(s -> Integer.valueOf(s));System.out.println(result);}
}

示例五

使用IntConsumer接口打印数组,该接口用于接收一个整数并不做任何处理直接返回,先使用匿名内部类的写法调用该方法。

import java.util.function.IntConsumer;public class Demo5 {public static void foreachArr(IntConsumer consumer){int[] arr = {1,2,3,4,5,6,7,8,9,10};for (int i : arr) {consumer.accept(i);}}public static void main(String[] args) {foreachArr(new IntConsumer() {@Overridepublic void accept(int value) {System.out.println(value);}});}
}

Lambda写法:

import java.util.function.IntConsumer;public class Demo5 {public static void foreachArr(IntConsumer consumer){int[] arr = {1,2,3,4,5,6,7,8,9,10};for (int i : arr) {consumer.accept(i);}}public static void main(String[] args) {foreachArr(value -> System.out.println(value));}
}

通过上述案例我们可以得到下面的省略规则

Lambda省略规则
  1. 参数类型可以省略

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

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

这些规则可以不记忆,因为idea非常强大,我们不必一步到位写出Lambda简化后的某些匿名内部类,可以先写出匿名内部类,然后用Alt+enter快捷键直接改成Lambda的版本。

Stream流

概述

 Stream是Java8 引入的新成员,它可以被用于处理集合或数组进行链状式的操作,可以更加方便的对数组或集合进行操作。我们可以将流想象成工厂里面的流水线,工人只需不断对流水线上过来的东西进行一一系列的处理,当走完了这条线东西就出来了。Stream流处理集合或数组如下图所示

在这里插入图片描述

为了后面的类中的代码更加简洁,在此引入lombok

    <dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.16</version></dependency></dependencies>

案例数组准备

我们准备两个类分别是作者和书籍

Author类

import lombok.Data;import java.awt.print.Book;
import java.util.List;@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Author {//idprivate Long id;//姓名private String name;//年龄private Integer age;//简介private String intro;//作品private List<Book> books;
}

Book类

import lombok.Data;@Data
@AllArgsConstructor
@NoArgsConstructor
@EqualsAndHashCode
public class Book {//idprivate Long id;//书名private String name;//分类private String category;//评分private Integer score;//简介private String intro;}

构造数据

使用该方法构造出一个存储Author的List集合

    private static List<Author> getAuthors() {//数据初始化Author author = new Author(1L,"蒙多",33,"一个从菜刀中明悟哲理的祖安人",null);Author author2 = new Author(2L,"亚拉索",15,"狂风也追逐不上他的思考速度",null);Author author3 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);Author author4 = new Author(3L,"易",14,"是这个世界在限制他的思维",null);//书籍列表List<Book> books1 = new ArrayList<>();List<Book> books2 = new ArrayList<>();List<Book> books3 = new ArrayList<>();books1.add(new Book(1L,"刀的两侧是光明与黑暗","哲学,爱情",88,"用一把刀划分了爱恨"));books1.add(new Book(2L,"一个人不能死在同一把刀下","个人成长,爱情",99,"讲述如何从失败中明悟真理"));books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));books2.add(new Book(3L,"那风吹不到的地方","哲学",85,"带你用思维去领略世界的尽头"));books2.add(new Book(4L,"吹或不吹","爱情,个人传记",56,"一个哲学家的恋爱观注定很难把他所在的时代理解"));books3.add(new Book(5L,"你的剑就是我的剑","爱情",56,"无法想象一个武者能对他的伴侣这么的宽容"));books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));books3.add(new Book(6L,"风与剑","个人传记",100,"两个哲学家灵魂和肉体的碰撞会激起怎么样的火花呢?"));author.setBooks(books1);author2.setBooks(books2);author3.setBooks(books3);author4.setBooks(books3);List<Author> authorList = new ArrayList<>(Arrays.asList(author,author2,author3,author4));return authorList;}

常规操作

1. 创建流

(1)单列集合:集合对象.stream()
public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();Stream<Author> stream = authors.stream();}}
(2)数组:Arrays.stream(数组)或者使用Stream.of()来创建
public class Demo6 {public static void main(String[] args) {Integer [] arr = {1, 2, 3, 4, 5};Stream<Integer> stream1 = Arrays.stream(arr);Stream<Integer> arr1 = Stream.of(arr);}
}
(3)双列集合:双列集合无法直接转成流必须转成单列集合在创建流
public class Demo6 {public static void main(String[] args) {Map<String,Integer> map = new HashMap<String,Integer>();map.put("张三",20);map.put("李四",10);map.put("王五",28);Stream<Map.Entry<String, Integer>> stream = map.entrySet().stream();}
}

2. 中间操作

中间方法指的是调用完成后会返回新的Stream流,可以继续使用(支持链式编程)。

  1. filter

可以对流中的元素进行条件过滤,符合条件的继续留在流中

比如,打印出姓名长度大于1的作家的姓名

import java.util.*;import java.util.stream.Stream;public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();authors.stream().filter(author -> author.getName().length()>1).forEach(author -> System.out.println(author.getName()));}   
}

运行结果:
在这里插入图片描述

map

对元素进行加工,并返回对应的新流

比如:打印所有作家的姓名

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();authors.stream().map(author -> author.getName()).forEach(name -> System.out.println(name));}
} 

运行结果:
在这里插入图片描述

distinct

去除重复的元素

比如:打印所有作家的姓名,并且要求其中不能有重复元素。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();authors.stream().distinct().forEach(Author-> System.out.println(Author.getName()));}
}    

运行结果:

在这里插入图片描述

sorted

​ 可以对流中的元素进行排序。

比如:对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();//升序authors.stream().sorted((o1,o2)->o1.getAge()-o2.getAge()).forEach(author-> System.out.println(author.getAge()));}
}    

运行结果:

在这里插入图片描述

注意:如果调用空参的sorted()方法,需要流中的元素是实现了Comparable。

limit

可以设置流的最大长度,超出的部分将被抛弃。

比如:对流中的元素按照年龄进行降序排序,并且要求不能有重复的元素,然后打印其中年龄最大的两个作家的姓名。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();authors.stream().distinct().sorted((o1, o2) -> o2.getAge()-o1.getAge()).limit(2).forEach(author-> System.out.println(author.getName()));}
}       

运行结果:

在这里插入图片描述

skip

跳过流中的前n个元素,返回剩下的元素

比如:打印除了年龄最大的作家外的其他作家,要求不能有重复元素,并且按照年龄降序排序。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();authors.stream().distinct().sorted((o1, o2) -> o2.getAge()-o1.getAge()).skip(1).forEach(author-> System.out.println(author.getName()));}
}    

运行结果:
在这里插入图片描述

flatMap

​ map只能把一个对象转换成另一个对象来作为流中的元素。而flatMap可以把一个对象转换成多个对象作为流中的元素。

例一:打印所有书籍的名字。要求对重复的元素进行去重。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();//将每个作者的作品提取出来转换成新的流authors.stream().flatMap(author->author.getBooks().stream()).distinct().forEach(book-> System.out.println(book.getName()));}
}        

运行结果:
在这里插入图片描述

concat

合并a和b两个流为一个流

比如,将两个整数流合并成一个流并输出

public class Demo6 {public static void main(String[] args) {Stream<Integer> stream1 = Stream.of(1, 2, 3);Stream<Integer> stream2 = Stream.of(4, 5, 6);Stream<Integer> combinedStream = Stream.concat(stream1, stream2);combinedStream.forEach(System.out::println);  // 输出 1, 2, 3, 4, 5, 6}
}    
  1. 终结操作
forEach

​ 对流中的元素进行遍历操作,我们通过传入的参数去指定对遍历到的元素进行什么具体操作。

比如:输出所有作家的名字

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();authors.stream().map(author->author.getName()).distinct().forEach(name -> System.out.println(name));}
}    

运行结果:

在这里插入图片描述

count

​ 可以用来获取当前流中元素的个数。

比如:打印这些作家的所出书籍的数目,注意删除重复元素。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();long count = authors.stream().flatMap(author -> author.getBooks().stream()).distinct().count();System.out.println(count);}
}    

运行结果:
在这里插入图片描述

max&min

​ 可以用来或者流中的最值。

比如:分别获取这些作家的所出书籍的最高分和最低分并打印。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();Optional<Integer> max = authors.stream().flatMap(author -> author.getBooks().stream()).map(book -> book.getScore()).max((score1, score2) -> score1 - score2);Optional<Integer> min = authors.stream().flatMap(author -> author.getBooks().stream()).map(book -> book.getScore()).min((score1, score2) -> score1 - score2);System.out.println("max:"+max.get());System.out.println("min:"+min.get());}
}    

运行结果;
在这里插入图片描述

collect

​ 把当前流转换成一个集合。

比如:获取一个存放所有作者名字的List集合

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();List<String> collect = authors.stream().map(author -> author.getName()).distinct().collect(Collectors.toList());System.out.println(collect);}
}    

在这里插入图片描述

​ 比如:获取一个所有书名的Set集合。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();Set<Book> collect = authors.stream().flatMap(author -> author.getBooks().stream()).collect(Collectors.toSet());System.out.println(collect);}
}    

运行结果:

在这里插入图片描述

​ 比如:获取一个Map集合,map的key为作者名,value为List

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();Map<String, List<Book>> map = authors.stream().distinct().collect(Collectors.toMap(author -> author.getName(), author -> author.getBooks()));System.out.println(map);}
}    

运行结果:

在这里插入图片描述

3. 查找与匹配

anyMatch

​ 可以用来判断是否有任意符合匹配条件的元素,结果为boolean类型。

比如:判断是否有年龄在30以上的作家

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();boolean b = authors.stream().anyMatch(author -> author.getAge() > 30);System.out.println(b);//true}
}    
allMatch

​ 可以用来判断是否都符合匹配条件,结果为boolean类型。如果都符合结果为true,否则结果为false。

比如:判断是否所有的作家都是成年人

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();boolean b = authors.stream().allMatch(author -> author.getAge() >=18);System.out.println(b);//false/`    
}    
noneMatch

​ 可以判断流中的元素是否都不符合匹配条件。如果都不符合结果为true,否则结果为false

比如:判断作家是否都没有超过100岁的。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();boolean b = authors.stream().noneMatch(author -> author.getAge() > 100);System.out.println(b);//true}
}    
findFirst

​ 获取流中的第一个元素。

比如:获取一个年龄最小的作家,并输出他的姓名。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();Optional<Author> first = authors.stream().sorted((o1, o2) -> o1.getAge() - o2.getAge()).findFirst();first.ifPresent(author -> System.out.println(author.getName()));}
}    
reduce

该方法能对流中的数据按照我们所指定的方式计算,我们需要初始化一个值,它就会按照我们指定的计算方式依次拿流中的元素和初始值进行计算.计算结果在和流后面的元素进行计算。

比如,使用reduce计算所有作者年龄的和

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();Integer reduce = authors.stream().distinct().map(author -> author.getAge()).reduce(0, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer integer, Integer integer2) {return integer+integer2;}});System.out.println(reduce);}
}    

因为是累加所以初始值设定为0.

​ 使用reduce求所有作者中年龄的最小值

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();Integer min = authors.stream().map(author -> author.getAge()).reduce(Integer.MAX_VALUE, new BinaryOperator<Integer>() {@Overridepublic Integer apply(Integer result, Integer element) {return result > element ? element : result;}});System.out.println(min);}
}    

4. 函数式接口中默认方法

1. and

我们在使用Predicate接口时候可能需要进行判断条件的拼接。而and方法相当于是使用&&来拼接两个判断条件

例如:打印作家中年龄大于17并且姓名的长度大于1的作家。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();Stream<Author> stream = authors.stream();stream.filter(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge()>17;}}.and(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getName().length()>1;}})).forEach(author-> System.out.println(author));}
}       
2. or

我们在使用Predicate接口时候可能需要进行判断条件的拼接。而or方法相当于是使用||来拼接两个判断条件。

例如:打印作家中年龄大于17或者姓名的长度小于2的作家

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();Stream<Author> stream = authors.stream();stream.filter(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge()>17;}}.or(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getName().length()<2;}})).forEach(author-> System.out.println(author));}
}    
3. negate

Predicate接口中的方法。negate方法相当于是在判断添加前面加了个! 表示取反

例如:打印作家中年龄不大于17的作家。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();Stream<Author> stream = authors.stream();stream.filter(new Predicate<Author>() {@Overridepublic boolean test(Author author) {return author.getAge()>17;}}.negate()).forEach(author-> System.out.println(author));}
}    

注意事项

  • 对流进行操作如果没有终结操,那么所有的中间过程都不会i进行操作。
  • 一旦已经经过了最终的操作,那么这个流就不能再使用。
  • 我们对流进行了很多中间操作,但是不会影响原来的数据。

高级用法

流元素类型转换

由于Java中很多的Stream的方法都用到 了泛型,所以方法的参数和返回值基本都是引用类型。当我们使用的时候就会涉及大量的自动装箱和自动拆箱,比如说我们对流中数据进行普通的计算(加减乘除)就会涉及到自动拆箱,返回的时候就要自动装箱,所以这就造成了一定的时间消耗,虽然时间很短,但是面对流大量的数据时候,这个时间就非常的耗时了。所以为了能对这部分时间消耗进行优化,Stream还提供了很多专门针对基本数据类型的方法。这些方法都会将流中的元素转成基本数据类型流。

​ 例如:mapToInt,mapToLong,mapToDouble,flatMapToInt,flatMapToDouble等。

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();long start1 =System.currentTimeMillis();authors.stream().map(author -> author.getAge()).map(age -> age + 10).filter(age->age>18).map(age->age+2).forEach(System.out::println);long end1 =System.currentTimeMillis();System.out.println("转换前:"+(end1-start1));//50long start2 =System.currentTimeMillis();authors.stream().mapToInt(author -> author.getAge()).map(age -> age + 10).filter(age->age>18).map(age->age+2).forEach(System.out::println);long end2 =System.currentTimeMillis();System.out.println("转换后:"+(end2-start2));//4}
}    

对上述的代码计算其运行时间可知,使用了mapToInt的程序比没有使用的程序运行效率高了10倍左右。

并行流

当流中有大量的元素的时候,我们可以使用并行流去提高操作效率。所谓的并行流就是充分的利用多核CPU,将任务分配给多个线程去 执行。Stream流中提供了方法正好支持并行操作。

  1. parallel

paralle方法可以将普通的顺序流转成并行流,适合用于在现有流的基础上进行转换。

public class Demo6 {public static void main(String[] args) {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);Integer sum = stream.parallel()//打印线名称.peek(new Consumer<Integer>() {@Overridepublic void accept(Integer num) {System.out.println(num+Thread.currentThread().getName());}}).filter(num -> num > 5).reduce((result, ele) -> result + ele).get();System.out.println(sum);}}
  1. parallelStream

parallelStream方法也可以得到并行流,更适合从集合开始获取并行流

public class Demo6 {public static void main(String[] args) {List<Author> authors = getAuthors();authors.parallelStream().map(author -> author.getAge()).map(age -> age + 10).filter(age->age>18).map(age->age+2).forEach(age -> System.out.println(age));}
}    

各位看官如果觉得文章写得不错,点赞评论关注走一波!谢谢啦!。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/84268.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

webpack复习

webpack webpack复习 webpack基本配置 拆分配置 - 公共配置 生产环境配置 开发环境配置 使用merge webpack-dev-server 启动本地服务 在公共中引入babel-loader处理es6 webpack高级配置 多入口文件 enty 入口为一个对象 里面的key为入口名 value为入口文件路径 例如 pa…

xxx酒业有限责任公司突发环境事件应急预案WORD

导读&#xff1a;原文《xxx酒业有限责任公司突发环境事件应急预案word》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 目 录 1 总则 1.1 编制目的 1.2 编制…

【Git】 git push origin master Everything up-to-date报错

hello&#xff0c;我是索奇&#xff0c;可以叫我小奇 git push 出错&#xff1f;显示 Everything up-to-date 那么看看你是否提交了message 下面是提交的简单流程 git add . git commit -m "message" git push origin master 大多数伙伴是没写git commit -m "…

在elementUI的表格(table)内嵌入svg图标

参考文档&#xff1a; https://element.eleme.cn/#/zh-CN/component/table demo效果图如下&#xff08;在表格的类型列中添加一个对应类型的svg图标&#xff09;&#xff1a; 本文主要关注以下两点&#xff1a; elementUI的表格&#xff08;table&#xff09;的自定义列模…

用python做一个小游戏代码,用python制作一个小游戏

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;如何用python编写一个简单的小游戏&#xff0c;用python做一个小游戏代码&#xff0c;今天让我们一起来看看吧&#xff01; 今天呢&#xff0c;给大家展示一下Python有趣的小地方&#xff0c;展示给大家看看&#xff0c…

QMainwindow窗口

QMainwindow窗口 菜单栏在二级菜单中输入中文的方法给菜单栏添加相应的动作使用QMenu类的API方法添加菜单项分隔符也是QAction类 工具栏状态栏停靠窗口 菜单栏 只能有一个, 位于窗口的最上方 关于顶级菜单可以直接在UI窗口中双击, 直接输入文本信息即可, 对应子菜单项也可以通…

【C++学习手札】new和delete看这一篇就够了!

​ 食用指南&#xff1a;本文在有C基础的情况下食用更佳 &#x1f340;本文前置知识&#xff1a; C类 ♈️今日夜电波&#xff1a; Prover—milet 1:21 ━━━━━━️&#x1f49f;──────── 4:01 …

安卓如何卸载应用

卸载系统应用 首先需要打开手机的开发者选项&#xff0c;启动usb调试。 第二步需要在电脑上安装adb命令&#xff0c;喜欢的话还可以将它加入系统path。如果不知道怎么安装&#xff0c;可以从这里下载免安装版本。 第三步将手机与电脑用数据线连接&#xff0c;注意是数据线&a…

Linux mysql5.7开启 binlog

查看 mysql是否开启 binlog。 查看命令&#xff1a; show variables like %log_bin%; log_bin OFF 是关闭的状态。 编辑my.cnf配置文件 vim /etc/my.cnf 默认的配置文件内容&#xff1a; 增加下面内容 server_id 1 binlog_format ROW log-bin mysql_log_bin 重启mysq…

C++友元函数和友元类的使用

1.友元介绍 在C中&#xff0c;友元&#xff08;friend&#xff09;是一种机制&#xff0c;允许某个类或函数访问其他类的私有成员。通过友元&#xff0c;可以授予其他类或函数对该类的私有成员的访问权限。友元关系在一些特定的情况下很有用&#xff0c;例如在类之间共享数据或…

pdf怎么删除不要的页面?这几种删除方法了解一下

pdf怎么删除不要的页面&#xff1f;在处理pdf文档时&#xff0c;我们经常会遇到需要删除某些页面的情况。一些多余或无关的页面可能会对文档的整体结构造成混乱&#xff0c;甚至会影响文档的可读性。此外&#xff0c;删除多余页面还可以减小文件大小&#xff0c;方便存储和传输…

每天五分钟机器学习:梯度下降算法和正规方程的比较

本文重点 梯度下降算法和正规方程是两种常用的机器学习算法,用于求解线性回归问题。它们各自有一些优点和缺点,下面将分别对它们进行详细的讨论。 区别 1. 梯度下降算法是一种迭代的优化算法,通过不断迭代调整参数来逼近最优解。它的基本思想是根据目标函数的梯度方向,沿…

springboot房地产管理java购房租房二手房j客户sp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 springboot房地产管理 系统1权限&#xff1a;管理员 …

基于SLAM的规划算法仿真复现|SLAM|智能规划

图片来自百度百科 前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量博客汇总https://blog.csdn.n…

go-zero 是如何实现令牌桶限流的?

原文链接&#xff1a; 上一篇文章介绍了 如何实现计数器限流&#xff1f;主要有两种实现方式&#xff0c;分别是固定窗口和滑动窗口&#xff0c;并且分析了 go-zero 采用固定窗口方式实现的源码。 但是采用固定窗口实现的限流器会有两个问题&#xff1a; 会出现请求量超出限…

Apoll 多项式规划求解

一、纵向规划 void QuarticPolynomialCurve1d::ComputeCoefficients(const float x0, const float dx0, const float ddx0, const float dx1,const float ddx1, const float p) {if (p < 0.0) {std::cout << "p should be greater than 0 at line 140." &…

MySQL中基础查询语句

用户表user数据如下&#xff1a; iddevice_idgenderageuniversityprovince12138male21北京大学Beijing23214male复旦大学Shanghai36543famale20北京大学Deijing42315female 23 浙江大学ZheJiang55432male25山东大学Shandong 1&#xff0c;写出ddl语句创建如上表&#xff0c;…

解密Redis:应对面试中的缓存相关问题2

面试官&#xff1a;Redis集群有哪些方案&#xff0c;知道嘛&#xff1f; 候选人&#xff1a;嗯~~&#xff0c;在Redis中提供的集群方案总共有三种&#xff1a;主从复制、哨兵模式、Redis分片集群。 面试官&#xff1a;那你来介绍一下主从同步。 候选人&#xff1a;嗯&#xff…

设计模式行为型——模板模式

目录 模板模式的定义 模板模式的实现 模板模式角色 模板模式类图 模板模式举例 模板模式代码实现 模板模式的特点 优点 缺点 使用场景 注意事项 实际应用 模板模式的定义 模板模式&#xff08;Template Pattern&#xff09;属于行为型设计模式&#xff0c;又叫模版…

第7章 通过内网本机IP获取微信code值及其对code值的回调。

在第5章中讲述了怎样通过内网穿透外外网从而获取微信code值&#xff0c;实际上微信测试帐号管理页中也支持通过内网本机IP获取微信code值。 1 重构launchSettings.json "https": { "commandName": "Project", "dotnetRunMessages": t…