Java8常用的新特性详解

网友投稿 274 2023-01-18

Java8常用的新特性详解

一、java 8 新特性的简介

速度更快

代码更少(增加了新的语法:Lambda表达式)强大的Stream API

便于并行

最大化减少空指针异常:Optional

Nashorn引擎,允许在JVM上运行js应用

二、Lambda表达式

Lambda表达式:特殊的匿名内部类,语法更简洁。

Lanbda表达式允许把函数作为一个方法的参数(函数作为方法参数传递),将代码像数据一样传递。

基本语法:

<函数式接口> <变量名> = (参数1,参数2...) ->{

//方法体

}

Lambda引入了新的操作符:->(箭头操作符),->将表达式分成两部分

左侧:(参数1,参数2…)表示参数列表。

右侧:{}内部是方法体

Lambda需要注意的事项:

形参列表的数据类型会自动推断

如果形参列表为空,只需保留()

如果形参只有1个,()可以省略,只需要参数的名称即可

如果执行语句只有一句,且无返回值,{}可以省略,若有返回值,则若想省去{},则必须同时省略return,且执行语句也保证只有一句

Lambda不会生成一个单独的内部类文件

2.1 lambda代码说明

语法格式一:

lambda 无参,无返回值

//如何使用lambda表达式

public class Demo1 {

public static void main(String[] args) {

//线程//匿名实现类对象---以前的写法

// Runnable runnable=new Runnable() {

// @Override

// public void run() {

// System.out.println("hello world!");

// }

// };

//lambda表达式写法

Runnable runnable1= ()->System.out.println("hello world!");

new Thread(runnable1).start();

//更简单的写法

new Thread(()->System.out.println("hello world!")).start();

}

}

语法格式二:

lambda 有一个参,无返回值

@Test

public void test02(){

Consumer con = new Consumer() {

@Override

public void accept(String s){

System.out.println(s);

}

};

con.accept("hello world!");

System.out.println("*********************");

//Lambda表达式

Consumer con1 = (String str)-> System.out.println(str);

con1.accept("hello world");

}

语法格式三:

数据类型可以省略,因为可由编译器推断得出,称为“类型推断”

@Test

public void test03(){

Consumer con1 = (str) -> System.out.println(str);

con1.accept("hello world");

}

三、函数式接口

如果一个接口只有一个抽象方法,则该接口称之为函数式接口,函数式接口可以使用Lambda表达式,Lambda表达式会被匹配到这个抽象方法上。

@FunctionalInterface注解检测接口是否符合函数式接口

public class Demo1 {

public static void main(String[] args) {

USB usb = new USB() {

@Override

public void show() {

System.out.println("我是函数式接口");

}

};

USB usb1=()-> System.out.println("你好");

info(()-> System.out.println("你好嘿嘿嘿"));

}

public static void info(USB usb){

usb.show();

}

}

//函数式接口

interface USB{

public void show();

}

lambda新增了四个重要的函数式接口:

函数形接口

供给形接口

消费型接口

判断型接口

函数式接口说明

public class Demo2 {

public static void main(String[] args) {

// Consumer consumer=t-> System.out.println("吃饭消费掉:"+t);

// Consumer consumer=new Consumer() {

// @Override

// public void accept(Double aDouble) {

// System.out.println("你消费得金额:"+aDouble);

// }

// };

Consumer consumer1=t ->System.out.println("吃饭消费掉:"+t);

Consumer consumer2=t ->System.out.println("唱歌消费掉:"+t);

Consumer consumer3=t ->System.out.println("洗脚消费掉:"+t);

hobby(consumer1,1000);

hobby(consumer2,2000);

hobby(consumer3,4000);

Supplier supplier=new Supplier() {

@Override

public Integer get() {

return new Random().nextInt(10);

}

};

Supplier supplier1=()->new Random().nextInt(10);

int[] arr = getArr(supplier1, 5);

System.out.println(Arrays.toString(arr));

System.out.println("~~~~~~~~~~~~~~~function~~~~~~~~~~~~~~~~~~~~~~~");

// Function function1=new Function() {

// @Override

// public String apply(String s) {

// return s.toUpperCase();

// }

// };

// Function function=s->s.toUpperCase();

// System.out.println(toUpper(function, "hello"));

List list=new ArrayList<>();

list.add("zhangsan");

list.add("lisi");

list.add("wangwu");

list.add("zhaoliu");

list.add("tianqi");

// Predicate predicate=new Predicate() {

// @Override

// public boolean test(String s) {

// return s.length()>5;

// }

// };

Predicate predicate1=s->s.length()>5;

List list1 = predicate(predicate1, list);

System.out.println(list1);

}

//断言型接口 返回true/false经常用于判断

public static List predicate(Predicate predicate,List list){

List newList=new ArrayList<>();

for(int i=0;i

if(predicate.test(list.get(i))){

newList.add(list.get(i));

}

}

return newList;

}

//函数型接口 有参数,且需要返回值

public static String toUpper(Function function,String str){

return function.apply(str);

}

//消费性函数式接口 不需要返回值,有参数,经常用于迭代

public static void hobby(Consumer consumer,double money){

consumer.accept(money);

}

//供给型函数式接口 无参数,指定返回值类型,经常用于只注重过程的代码

public static int[] getArr(Supplier supplier,int count){

int [] arr=new int[count];

for(int i=0;i

arr[i]=supplier.get();

}

return arr;

}

}

四、方法引用

方法引用式Lambda表达式的一种简写形式。如果Lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用。

常见的方法引用:

(1)构造器引用

**格式:**类名::new

@Test

public void test04(){

//普通写法

Supplier supplier=new Supplier() {

@Override

public Emp get() {

return new Emp("刘德华");

}

};

//类名::new 方法引用

Supplier supplier=Emp::new; //必须该类中存在无参构造函数。

System.out.println(supplier.get());

}

@Data

@AllArgsConstructor

@NoArgsConstructor

class Emp{

private String name;

}

(2)静态方法引用

**格式:**类名::静态方法名

//类::静态方法 int compare(T o1, T o2);

//Lambda表达式方法引用

Comparator comparator=(o1,o2)->Integer.compare(o1,o2);

//静态方法引用Demo

Comparator comparator=Integer::compare;

int compare = comparator.compare(18, 18);

System.out.println(compare);

(3)类的方法引用

**格式:**类名::实例方法名

//lambda匿名方法引用

Function function=e->{

return e.getName();

};

//类名::实例方法 R apply(T t);

Function function=Emp::getName;

System.out.println(function.apply(new Emp("刘德华")));

(4)实例对象的方法引用

**格式:**对象::实例方法名

//对象::实例方法

//这里System.out就是一个对象

Consumer consumer2=System.out::println;

consumer2.accept("你是刘德华吗?");

五、Stream API

流(Stream)中保存对集合或数组数据的操作。和集合类似,但集合中保存的是数据。

特点:

Stream自己不会存储元素。

Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。

Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

步骤:

创建一个流。

在一个或多个步骤中,将初始化Stream转化到另一个Stream的中间操作。

使用一个终止操作来产生一个结果。该操作会强制它之前的延迟操作立即执行。在这之后,该Stream就不能使用了。

要注意的是,对流的操作完成后需要进行关闭操作(或者用JAVA7的try-with-resources)。

获取Stream对象的方式

通过Collection对象的stream()或parallelStream()方法

通过Arrays类的stream()方法

通过Stream接口的of()、iterate()、generate()方法

通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法

public class Demo1 {

public static void main(String[] args) {

//1.通过Collection得对象中stream方法或parallelStream

List list=new ArrayList<>();

list.add("apple");

list.add("huawei");

list.add("xiaomi");

list.add("vivo");

Stream stream = list.stream();//串行流

//遍历集合(T t)-{}vfAPsdE; 方法引用

stream.forEach(e->{

System.out.println(e);

});

//方法引用

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

Stream stringStream = list.parallelStream(); //并行流

//2.通过Arrays转化为流

int[] arr={2,34,5,6,7,2};

IntStream stream = Arrays.stream(arr);

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

//3.通过Stream中of,iterator,generator();

Stream list = Stream.of("java01", "java02", "java03");

static UnaryOperator identity() {

return t -> t;

}

UnaryOperator unaryOperator=new UnaryOperator() {

@Override

public Integer apply(Integer x) {

return x+5;

}

};

UnaryOperator unaryOperator=x->x+5;

Stream list = Stream.iterate(0,unaryOperator);//0,5,10,15,20,25,30

list.limit(10).forEach(System.out::println);

Supplier s

Supplier s=new Supplier() {

@Override

public Integer get() {

return new Random().nextInt(50);

}

};

Supplier s=()->new Random().nextInt(50);

Stream stream = Stream.generate(s);

Stream stream = Stream.generate(()->new Random().nextInt(50));

stream.limit(10).forEach(System.out::println);

//IntStream LongStream DoubleStream

IntStream stream = IntStream.rangeClosed(0, 90);

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

}

}

5.1 中间操作

中间操作.

filter、limit、skip、distinct、sorted

map

parallel

filter:接收Lambda,从流中排除某些操作;

limit:截断流,使其元素不超过给定对象

skip(n):跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补

distinct:筛选,通过流所生成元素的hashCode()和equals()去除重复元素。

代码操作

public class test02 {

public static void main(String[] args) {

//personList.stream()是创建流,filter()属于中间操作,forEach、count()是终止操作。

List personList = new ArrayList<>();

personList.add(new Person("欧阳雪",18,"中国",'F'));

personList.add(new Person("Tom",24,"美国",'M'));

personList.add(new Person("Tom",24,"美国",'M'));

personList.add(new Person("Harley",22,"英国",'F'));

personList.add(new Person("向天笑",20,"中国",'M'));

personList.add(new Person("李康",22,"中国",'M'));

pevfAPsdErsonList.add(new Person("小梅",20,"中国",'F'));

personList.add(new Person("何雪",21,"中国",'F'));

persohttp://nListvfAPsdE.add(new Person("李康",22,"中国",'M'));

//找出大于21岁的人

personList.stream().filter((person) -> person.getAge()>21).forEach(System.out::println);

System.out.println("----------------------");

//查询中国人有几个

long num = personList.stream().filter(p ->p.getCountry().equals("中国")).count();

System.out.println("中国人有:"+num+"个");

System.out.println("---------------------------");

//从Person列表中取出两个女性。

personList.stream().filter((p) -> p.getSex() == 'F').limit(2).forEach(System.out::println);

System.out.println("----------------------------");

//从Person列表中从第2个女性开始,取出所有的女性。

personList.stream().filter((p) -> p.getSex() == 'F').skip(1).forEach(System.out::println);

System.out.println("-------------------------------");

//去除掉了一个重复的数据

personList.stream().filter((p) -> p.getSex() == 'M').distinct().forEach(System.out::println);

}

测试结果

在这个例子中,personList.stream()是创建流,filter()、limit()、skip()、distinct()属于中间操作,forEach、count()是终止操作。

5.2 Stream中间操作–映射

map–接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

flatMap–接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

map举例

例:比如,我们用一个PersonCountry类来接收所有的国家信息:

System.out.println("**************************");

personList.stream().map((p) -> {

Person personName = new Person();

personName.setCountry(p.getCountry());

return personName;

}).distinct().forEach(System.out::println);

测试结果

5.3 Stream中间操作–排序

sorted()–自然排序(Comparable)

sorted(Comparator com)–定制排序(Comparator)

自然排序比较好理解,这里只讲一下定制排序,对前面的personList按年龄从小到大排序,年龄相同,则再按姓名排序:

final Stream sorted = personList.stream().sorted((p1, p2) -> {

if (p1.getAge().equals(p2.getAge())) {

return p1.getName().compareTo(p2.getName());

} else {

return p1.getAge().compareTo(p2.getAge());

}

});

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

运行结果

5.4 终止操作

forEach、min、max、count

reduce、collect

allMatch–检查是否匹配所有元素

anyMatch–检查是否至少匹配一个元素

noneMatch–检查是否没有匹配所有元素

findFirst–返回第一个元素

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

count–返回流中元素的总个数

max–返回流中最大值

min–返回流中最小值

allMatch

判断personList中的人是否都是成年人:

final boolean adult = personList.stream().allMatch(p -> p.getAge() >= 18);

System.out.println("是否都是成年人:" + adult);

final boolean chinaese = personList.stream().allMatch(p -> p.getCountry().equals("中国"));

System.out.println("是否都是中国人:" + chinaese);

运行结果

max min

判断最大、最小的人信息

final Optional maxAge = personList.stream().max((p1, p2) -> p1.getAge().compareTo(p2.getAge()));

System.out.println("年龄最大的人信息:" + maxAge.get());

final Optional minAge = personList.stream().min((p1, p2) -> p1.getAge().compareTo(p2.getAge()));

System.out.println("年龄最小的人信息:" + minAge.get());

运行结果

求一个1到100的和

List integerList = new ArrayList<>(100);

for(int i = 1;i <= 100;i++) {

integerList.add(i);

}

final Integer reduce = integerList.stream().reduce(0, (x, y) -> x + y);

System.out.println("结果为:" + reduce);

运行结果

求所有人的年龄之和

final Optional reduce =

personList.stream().map(Person::getAge).reduce(Integer::sum);

System.out.println("年龄总和:" + reduce);

年龄总和:193

改写map举例中的的例子,将国家收集起来转换成List

final List collect = personList.stream().map(p ->

p.getCountry()).distinct().collect(Collectors.toList());

System.out.println(collect);

输出结果:[中国, 美国, 英国]

计算出平均年龄

final Double collect1 =

personList.stream().collect(Collectors.averagingInt(p -> p.getAge()));

System.out.println("平均年龄为:" + collect1);

平均年龄为:21.444444444444443

注意流的关闭

try(final Stream integerStream = personList.stream().map(Person::getAge)) {

final Optional minAge = integerStream.collect(Collectors.minBy(Integer::compareTo));

System.out.println(minAge.get());

}

if(predicate.test(list.get(i))){

newList.add(list.get(i));

}

}

return newList;

}

//函数型接口 有参数,且需要返回值

public static String toUpper(Function function,String str){

return function.apply(str);

}

//消费性函数式接口 不需要返回值,有参数,经常用于迭代

public static void hobby(Consumer consumer,double money){

consumer.accept(money);

}

//供给型函数式接口 无参数,指定返回值类型,经常用于只注重过程的代码

public static int[] getArr(Supplier supplier,int count){

int [] arr=new int[count];

for(int i=0;i

arr[i]=supplier.get();

}

return arr;

}

}

四、方法引用

方法引用式Lambda表达式的一种简写形式。如果Lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用。

常见的方法引用:

(1)构造器引用

**格式:**类名::new

@Test

public void test04(){

//普通写法

Supplier supplier=new Supplier() {

@Override

public Emp get() {

return new Emp("刘德华");

}

};

//类名::new 方法引用

Supplier supplier=Emp::new; //必须该类中存在无参构造函数。

System.out.println(supplier.get());

}

@Data

@AllArgsConstructor

@NoArgsConstructor

class Emp{

private String name;

}

(2)静态方法引用

**格式:**类名::静态方法名

//类::静态方法 int compare(T o1, T o2);

//Lambda表达式方法引用

Comparator comparator=(o1,o2)->Integer.compare(o1,o2);

//静态方法引用Demo

Comparator comparator=Integer::compare;

int compare = comparator.compare(18, 18);

System.out.println(compare);

(3)类的方法引用

**格式:**类名::实例方法名

//lambda匿名方法引用

Function function=e->{

return e.getName();

};

//类名::实例方法 R apply(T t);

Function function=Emp::getName;

System.out.println(function.apply(new Emp("刘德华")));

(4)实例对象的方法引用

**格式:**对象::实例方法名

//对象::实例方法

//这里System.out就是一个对象

Consumer consumer2=System.out::println;

consumer2.accept("你是刘德华吗?");

五、Stream API

流(Stream)中保存对集合或数组数据的操作。和集合类似,但集合中保存的是数据。

特点:

Stream自己不会存储元素。

Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。

Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

步骤:

创建一个流。

在一个或多个步骤中,将初始化Stream转化到另一个Stream的中间操作。

使用一个终止操作来产生一个结果。该操作会强制它之前的延迟操作立即执行。在这之后,该Stream就不能使用了。

要注意的是,对流的操作完成后需要进行关闭操作(或者用JAVA7的try-with-resources)。

获取Stream对象的方式

通过Collection对象的stream()或parallelStream()方法

通过Arrays类的stream()方法

通过Stream接口的of()、iterate()、generate()方法

通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法

public class Demo1 {

public static void main(String[] args) {

//1.通过Collection得对象中stream方法或parallelStream

List list=new ArrayList<>();

list.add("apple");

list.add("huawei");

list.add("xiaomi");

list.add("vivo");

Stream stream = list.stream();//串行流

//遍历集合(T t)-{}vfAPsdE; 方法引用

stream.forEach(e->{

System.out.println(e);

});

//方法引用

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

Stream stringStream = list.parallelStream(); //并行流

//2.通过Arrays转化为流

int[] arr={2,34,5,6,7,2};

IntStream stream = Arrays.stream(arr);

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

//3.通过Stream中of,iterator,generator();

Stream list = Stream.of("java01", "java02", "java03");

static UnaryOperator identity() {

return t -> t;

}

UnaryOperator unaryOperator=new UnaryOperator() {

@Override

public Integer apply(Integer x) {

return x+5;

}

};

UnaryOperator unaryOperator=x->x+5;

Stream list = Stream.iterate(0,unaryOperator);//0,5,10,15,20,25,30

list.limit(10).forEach(System.out::println);

Supplier s

Supplier s=new Supplier() {

@Override

public Integer get() {

return new Random().nextInt(50);

}

};

Supplier s=()->new Random().nextInt(50);

Stream stream = Stream.generate(s);

Stream stream = Stream.generate(()->new Random().nextInt(50));

stream.limit(10).forEach(System.out::println);

//IntStream LongStream DoubleStream

IntStream stream = IntStream.rangeClosed(0, 90);

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

}

}

5.1 中间操作

中间操作.

filter、limit、skip、distinct、sorted

map

parallel

filter:接收Lambda,从流中排除某些操作;

limit:截断流,使其元素不超过给定对象

skip(n):跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补

distinct:筛选,通过流所生成元素的hashCode()和equals()去除重复元素。

代码操作

public class test02 {

public static void main(String[] args) {

//personList.stream()是创建流,filter()属于中间操作,forEach、count()是终止操作。

List personList = new ArrayList<>();

personList.add(new Person("欧阳雪",18,"中国",'F'));

personList.add(new Person("Tom",24,"美国",'M'));

personList.add(new Person("Tom",24,"美国",'M'));

personList.add(new Person("Harley",22,"英国",'F'));

personList.add(new Person("向天笑",20,"中国",'M'));

personList.add(new Person("李康",22,"中国",'M'));

pevfAPsdErsonList.add(new Person("小梅",20,"中国",'F'));

personList.add(new Person("何雪",21,"中国",'F'));

persohttp://nListvfAPsdE.add(new Person("李康",22,"中国",'M'));

//找出大于21岁的人

personList.stream().filter((person) -> person.getAge()>21).forEach(System.out::println);

System.out.println("----------------------");

//查询中国人有几个

long num = personList.stream().filter(p ->p.getCountry().equals("中国")).count();

System.out.println("中国人有:"+num+"个");

System.out.println("---------------------------");

//从Person列表中取出两个女性。

personList.stream().filter((p) -> p.getSex() == 'F').limit(2).forEach(System.out::println);

System.out.println("----------------------------");

//从Person列表中从第2个女性开始,取出所有的女性。

personList.stream().filter((p) -> p.getSex() == 'F').skip(1).forEach(System.out::println);

System.out.println("-------------------------------");

//去除掉了一个重复的数据

personList.stream().filter((p) -> p.getSex() == 'M').distinct().forEach(System.out::println);

}

测试结果

在这个例子中,personList.stream()是创建流,filter()、limit()、skip()、distinct()属于中间操作,forEach、count()是终止操作。

5.2 Stream中间操作–映射

map–接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

flatMap–接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

map举例

例:比如,我们用一个PersonCountry类来接收所有的国家信息:

System.out.println("**************************");

personList.stream().map((p) -> {

Person personName = new Person();

personName.setCountry(p.getCountry());

return personName;

}).distinct().forEach(System.out::println);

测试结果

5.3 Stream中间操作–排序

sorted()–自然排序(Comparable)

sorted(Comparator com)–定制排序(Comparator)

自然排序比较好理解,这里只讲一下定制排序,对前面的personList按年龄从小到大排序,年龄相同,则再按姓名排序:

final Stream sorted = personList.stream().sorted((p1, p2) -> {

if (p1.getAge().equals(p2.getAge())) {

return p1.getName().compareTo(p2.getName());

} else {

return p1.getAge().compareTo(p2.getAge());

}

});

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

运行结果

5.4 终止操作

forEach、min、max、count

reduce、collect

allMatch–检查是否匹配所有元素

anyMatch–检查是否至少匹配一个元素

noneMatch–检查是否没有匹配所有元素

findFirst–返回第一个元素

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

count–返回流中元素的总个数

max–返回流中最大值

min–返回流中最小值

allMatch

判断personList中的人是否都是成年人:

final boolean adult = personList.stream().allMatch(p -> p.getAge() >= 18);

System.out.println("是否都是成年人:" + adult);

final boolean chinaese = personList.stream().allMatch(p -> p.getCountry().equals("中国"));

System.out.println("是否都是中国人:" + chinaese);

运行结果

max min

判断最大、最小的人信息

final Optional maxAge = personList.stream().max((p1, p2) -> p1.getAge().compareTo(p2.getAge()));

System.out.println("年龄最大的人信息:" + maxAge.get());

final Optional minAge = personList.stream().min((p1, p2) -> p1.getAge().compareTo(p2.getAge()));

System.out.println("年龄最小的人信息:" + minAge.get());

运行结果

求一个1到100的和

List integerList = new ArrayList<>(100);

for(int i = 1;i <= 100;i++) {

integerList.add(i);

}

final Integer reduce = integerList.stream().reduce(0, (x, y) -> x + y);

System.out.println("结果为:" + reduce);

运行结果

求所有人的年龄之和

final Optional reduce =

personList.stream().map(Person::getAge).reduce(Integer::sum);

System.out.println("年龄总和:" + reduce);

年龄总和:193

改写map举例中的的例子,将国家收集起来转换成List

final List collect = personList.stream().map(p ->

p.getCountry()).distinct().collect(Collectors.toList());

System.out.println(collect);

输出结果:[中国, 美国, 英国]

计算出平均年龄

final Double collect1 =

personList.stream().collect(Collectors.averagingInt(p -> p.getAge()));

System.out.println("平均年龄为:" + collect1);

平均年龄为:21.444444444444443

注意流的关闭

try(final Stream integerStream = personList.stream().map(Person::getAge)) {

final Optional minAge = integerStream.collect(Collectors.minBy(Integer::compareTo));

System.out.println(minAge.get());

}

arr[i]=supplier.get();

}

return arr;

}

}

四、方法引用

方法引用式Lambda表达式的一种简写形式。如果Lambda表达式方法体中只是调用一个特定的已经存在的方法,则可以使用方法引用。

常见的方法引用:

(1)构造器引用

**格式:**类名::new

@Test

public void test04(){

//普通写法

Supplier supplier=new Supplier() {

@Override

public Emp get() {

return new Emp("刘德华");

}

};

//类名::new 方法引用

Supplier supplier=Emp::new; //必须该类中存在无参构造函数。

System.out.println(supplier.get());

}

@Data

@AllArgsConstructor

@NoArgsConstructor

class Emp{

private String name;

}

(2)静态方法引用

**格式:**类名::静态方法名

//类::静态方法 int compare(T o1, T o2);

//Lambda表达式方法引用

Comparator comparator=(o1,o2)->Integer.compare(o1,o2);

//静态方法引用Demo

Comparator comparator=Integer::compare;

int compare = comparator.compare(18, 18);

System.out.println(compare);

(3)类的方法引用

**格式:**类名::实例方法名

//lambda匿名方法引用

Function function=e->{

return e.getName();

};

//类名::实例方法 R apply(T t);

Function function=Emp::getName;

System.out.println(function.apply(new Emp("刘德华")));

(4)实例对象的方法引用

**格式:**对象::实例方法名

//对象::实例方法

//这里System.out就是一个对象

Consumer consumer2=System.out::println;

consumer2.accept("你是刘德华吗?");

五、Stream API

流(Stream)中保存对集合或数组数据的操作。和集合类似,但集合中保存的是数据。

特点:

Stream自己不会存储元素。

Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。

Stream操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

步骤:

创建一个流。

在一个或多个步骤中,将初始化Stream转化到另一个Stream的中间操作。

使用一个终止操作来产生一个结果。该操作会强制它之前的延迟操作立即执行。在这之后,该Stream就不能使用了。

要注意的是,对流的操作完成后需要进行关闭操作(或者用JAVA7的try-with-resources)。

获取Stream对象的方式

通过Collection对象的stream()或parallelStream()方法

通过Arrays类的stream()方法

通过Stream接口的of()、iterate()、generate()方法

通过IntStream、LongStream、DoubleStream接口中的of、range、rangeClosed方法

public class Demo1 {

public static void main(String[] args) {

//1.通过Collection得对象中stream方法或parallelStream

List list=new ArrayList<>();

list.add("apple");

list.add("huawei");

list.add("xiaomi");

list.add("vivo");

Stream stream = list.stream();//串行流

//遍历集合(T t)-{}vfAPsdE; 方法引用

stream.forEach(e->{

System.out.println(e);

});

//方法引用

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

Stream stringStream = list.parallelStream(); //并行流

//2.通过Arrays转化为流

int[] arr={2,34,5,6,7,2};

IntStream stream = Arrays.stream(arr);

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

//3.通过Stream中of,iterator,generator();

Stream list = Stream.of("java01", "java02", "java03");

static UnaryOperator identity() {

return t -> t;

}

UnaryOperator unaryOperator=new UnaryOperator() {

@Override

public Integer apply(Integer x) {

return x+5;

}

};

UnaryOperator unaryOperator=x->x+5;

Stream list = Stream.iterate(0,unaryOperator);//0,5,10,15,20,25,30

list.limit(10).forEach(System.out::println);

Supplier s

Supplier s=new Supplier() {

@Override

public Integer get() {

return new Random().nextInt(50);

}

};

Supplier s=()->new Random().nextInt(50);

Stream stream = Stream.generate(s);

Stream stream = Stream.generate(()->new Random().nextInt(50));

stream.limit(10).forEach(System.out::println);

//IntStream LongStream DoubleStream

IntStream stream = IntStream.rangeClosed(0, 90);

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

}

}

5.1 中间操作

中间操作.

filter、limit、skip、distinct、sorted

map

parallel

filter:接收Lambda,从流中排除某些操作;

limit:截断流,使其元素不超过给定对象

skip(n):跳过元素,返回一个扔掉了前n个元素的流,若流中元素不足n个,则返回一个空流,与limit(n)互补

distinct:筛选,通过流所生成元素的hashCode()和equals()去除重复元素。

代码操作

public class test02 {

public static void main(String[] args) {

//personList.stream()是创建流,filter()属于中间操作,forEach、count()是终止操作。

List personList = new ArrayList<>();

personList.add(new Person("欧阳雪",18,"中国",'F'));

personList.add(new Person("Tom",24,"美国",'M'));

personList.add(new Person("Tom",24,"美国",'M'));

personList.add(new Person("Harley",22,"英国",'F'));

personList.add(new Person("向天笑",20,"中国",'M'));

personList.add(new Person("李康",22,"中国",'M'));

pevfAPsdErsonList.add(new Person("小梅",20,"中国",'F'));

personList.add(new Person("何雪",21,"中国",'F'));

persohttp://nListvfAPsdE.add(new Person("李康",22,"中国",'M'));

//找出大于21岁的人

personList.stream().filter((person) -> person.getAge()>21).forEach(System.out::println);

System.out.println("----------------------");

//查询中国人有几个

long num = personList.stream().filter(p ->p.getCountry().equals("中国")).count();

System.out.println("中国人有:"+num+"个");

System.out.println("---------------------------");

//从Person列表中取出两个女性。

personList.stream().filter((p) -> p.getSex() == 'F').limit(2).forEach(System.out::println);

System.out.println("----------------------------");

//从Person列表中从第2个女性开始,取出所有的女性。

personList.stream().filter((p) -> p.getSex() == 'F').skip(1).forEach(System.out::println);

System.out.println("-------------------------------");

//去除掉了一个重复的数据

personList.stream().filter((p) -> p.getSex() == 'M').distinct().forEach(System.out::println);

}

测试结果

在这个例子中,personList.stream()是创建流,filter()、limit()、skip()、distinct()属于中间操作,forEach、count()是终止操作。

5.2 Stream中间操作–映射

map–接收Lambda,将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。

flatMap–接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流

map举例

例:比如,我们用一个PersonCountry类来接收所有的国家信息:

System.out.println("**************************");

personList.stream().map((p) -> {

Person personName = new Person();

personName.setCountry(p.getCountry());

return personName;

}).distinct().forEach(System.out::println);

测试结果

5.3 Stream中间操作–排序

sorted()–自然排序(Comparable)

sorted(Comparator com)–定制排序(Comparator)

自然排序比较好理解,这里只讲一下定制排序,对前面的personList按年龄从小到大排序,年龄相同,则再按姓名排序:

final Stream sorted = personList.stream().sorted((p1, p2) -> {

if (p1.getAge().equals(p2.getAge())) {

return p1.getName().compareTo(p2.getName());

} else {

return p1.getAge().compareTo(p2.getAge());

}

});

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

运行结果

5.4 终止操作

forEach、min、max、count

reduce、collect

allMatch–检查是否匹配所有元素

anyMatch–检查是否至少匹配一个元素

noneMatch–检查是否没有匹配所有元素

findFirst–返回第一个元素

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

count–返回流中元素的总个数

max–返回流中最大值

min–返回流中最小值

allMatch

判断personList中的人是否都是成年人:

final boolean adult = personList.stream().allMatch(p -> p.getAge() >= 18);

System.out.println("是否都是成年人:" + adult);

final boolean chinaese = personList.stream().allMatch(p -> p.getCountry().equals("中国"));

System.out.println("是否都是中国人:" + chinaese);

运行结果

max min

判断最大、最小的人信息

final Optional maxAge = personList.stream().max((p1, p2) -> p1.getAge().compareTo(p2.getAge()));

System.out.println("年龄最大的人信息:" + maxAge.get());

final Optional minAge = personList.stream().min((p1, p2) -> p1.getAge().compareTo(p2.getAge()));

System.out.println("年龄最小的人信息:" + minAge.get());

运行结果

求一个1到100的和

List integerList = new ArrayList<>(100);

for(int i = 1;i <= 100;i++) {

integerList.add(i);

}

final Integer reduce = integerList.stream().reduce(0, (x, y) -> x + y);

System.out.println("结果为:" + reduce);

运行结果

求所有人的年龄之和

final Optional reduce =

personList.stream().map(Person::getAge).reduce(Integer::sum);

System.out.println("年龄总和:" + reduce);

年龄总和:193

改写map举例中的的例子,将国家收集起来转换成List

final List collect = personList.stream().map(p ->

p.getCountry()).distinct().collect(Collectors.toList());

System.out.println(collect);

输出结果:[中国, 美国, 英国]

计算出平均年龄

final Double collect1 =

personList.stream().collect(Collectors.averagingInt(p -> p.getAge()));

System.out.println("平均年龄为:" + collect1);

平均年龄为:21.444444444444443

注意流的关闭

try(final Stream integerStream = personList.stream().map(Person::getAge)) {

final Optional minAge = integerStream.collect(Collectors.minBy(Integer::compareTo));

System.out.println(minAge.get());

}

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Springboot Redis设置key前缀的方法步骤
下一篇:开放api接口(开放api接口什么意思)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~