目录
(1)接口名 对象名=(参数类型1参数名1,....参数类型n 参数名n)->{方法体;}
(4){}:存放重写的方法体内容。可以理解为对抽象方法的覆盖
Collection集合提供了 default Stream stream()获取流;
(2)count():Stream 流提供的count方法,统计其中的元素个数
(5)skip()方法: 跳过前几个元素,可以使用skip方法获取一个截取之后的新的集合
(7)sorted()方法可以默认泛型排序,也可以自定义排序规则
(8)match()如果需要判断数据是否匹配指定的条件。可以使用match方法
(8.2)anyMatch() 只要有一个满足条件就返回true
(8.3)noneMatch()所有的元素都不满足,返回true
(9)collect() 方:法收集是一个 最终操作,返回Stream中元素集合,返回值类型是集合(List、Set、Map)或 字符串。
Collectors.groupingBy() :可以按照指定内容进行统计
Collectors.mapping():将一种数据类型的集合映射成另一种数据类型
一、Lambda表达式
Lambda
表达式本质是一个匿名函数,用于把函数作为参数,传入方法中,实现函数式编程风格。- 使用
Lambda
表达式可以使代码变的更加简洁紧凑。
1、语法格式:
(1)接口名 对象名=(参数类型1参数名1,....参数类型n 参数名n)->{方法体;}
(2)参数类型h 参数名n:接口中抽象方法的参数项
(3)->:表示连接操作
(4){}:存放重写的方法体内容。可以理解为对抽象方法的覆盖
2、简写格式:
(1)参数类型可以简写
(2)小括号,当参数只有1个时,可以省略
(3){}、return、; 同时进行省略
package com.yuan.lambda;
public class Demo02 {
public static void main(String[] args) {
swim(new ISwim() {
@Override
public void swimming() {
System.out.println("Frog蛙泳");
}
});
swim(()-> System.out.println("Duck蛙泳"));
}
public static void swim(ISwim s1){
System.out.println("进入swim方法");
s1.swimming();
System.out.println("结束swim方法");
}
}
interface ISwim{
void swimming();
}
二、函数式接口
在 Java 8
中专门有一个包放函数式接口java.util.function
,该包下的所有接口都有 @FunctionalInterface
注解,提供函数式编程方式。下面是最常用的几个接口。
(1)Supplier接口 --供给型接口:
@FunctionalInterface
public interface Supplier<T> {
public abstract T get();
}java.util.function.Supplier<T> 接口 - 方法没有参数,有返回值--供给型接口。
它意味着"供给" , 对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。
供给型接口,通过Supplier接口中的get方法可以得到一个值,无参有返回的接口。
//案例
public class Demo01 {
public static void main(String[] args) {
System.out.println("进入到main方法中");
printMax(()->{
System.out.println("进入到get方法中");
Integer[] array={1,2,3,4,5};
Integer number= Collections.max(Arrays.asList(array));
System.out.println("在get中找到最大值了"+number);
return number;
});
Integer number = number(() -> {
while(true) {
int number1 = (int) (Math.random() * 11 + 10);
if((number1&1)==0){
return number1;
}
}
});
System.out.println("随机数为:"+number);
}
public static Integer number(Supplier<Integer> sup){
Integer ranNum=sup.get();
return ranNum;
}
public static void printMax(Supplier<Integer> sup){
System.out.println("机内到printMax方法中");
Integer number=sup.get();
System.out.println("printMax要打印的sup获取的最大值"+number);
}
}
(2)Consumer接口 --消费型接口:
@FunctionalInterface
public interface Consumer<T> {
public abstract void accept(T t);
}java.util.function.Consumer<T> 接口则正好相反 --方法有参数,没有返回值,它不是生产一个数据,而是消费一个数据,其数据类型由泛型参数决定。 --消费型接口
Consumer消费型接口,可以拿到accept方法参数传递过来的数据进行处理, 有参无返回的接口。
//案例
public class Demo02 {
public static void main(String[] args) {
//转大写
caseLetter(t->System.out.println(t.toUpperCase()),"HelloWorld");
//转小写
caseLetter(t->System.out.println(t.toLowerCase()),"HelloWorld");
//先转大写,再转小写
caseLetters(t->System.out.println(t.toUpperCase()),
t->System.out.println(t.toLowerCase()),"HelloWorld");
}
public static void caseLetter(Consumer<String> consumer,String str){
consumer.accept(str);
}
public static void caseLetters(Consumer<String> consumer1,Consumer<String> consumer2,String str){
consumer1.andThen(consumer2).accept(str);
}
}
(3)Function接口 --转换型接口:
@FunctionalInterface
public interface Function<T, R> {
public abstract R apply(T t);
}java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件, 后者称为后置条件。有参数有返回值。----- 此方法接收一个参数,加工处理成另一种,称为转换型接口
Function转换型接口,对apply方法传入的T类型数据进行处理,返回R类型的结果,有参有返回的接口。使用的场景 例如:将 String类型转换为 Integer类型。
//案例
public class Demo03 {
public static void main(String[] args) {
// 1.获取字符串的长度
Function<String, Integer> f1 = s1 -> s1.length();
test(f1, "1234abc");
// 2.截取字符串的前3位,将其转换成数字
test(s1 -> Integer.parseInt(s1.substring(0, 3)), "123aneii");
test(s1 -> s1.length(), len -> new int[len], "abc");
}
public static void test(Function<String, Integer> function, String str) {
Integer number = function.apply(str);
System.out.println(number);
}
public static void test(Function<String, Integer> f1,
Function<Integer, int[]> f2,
String str) {
int[] arr = f1.andThen(f2).apply(str);
System.out.println(Arrays.toString(arr));
}
}
(4)Predicate接口--断言型接口:
@FunctionalInterface
public interface Predicate<T> {
public abstract boolean test(T t);
}
Predicate接口用于做判断,返回boolean类型的值有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用
java.util.function.Predicate<T> 接口。------接收一个参数,返回一个boolean类型的值,称为判断型接口
//案例
public class Demo04 {
public static void main(String[] args) {
int number = new Random().nextInt(200);
// 1.判断此数字是否大于等于100
method(num -> num >= 100, number);
// 2.判断此数字是否是偶数
method(num -> (num & 1) == 0, number);
methods(num -> num >= 100, num -> (num & 1) == 0, number);
}
public static void method(Predicate<Integer> p, Integer num) {
boolean b = p.test(num);
System.out.println("数字num:" + num + "判断后的结果为:" + b);
}
public static void methods(Predicate<Integer> p1, Predicate<Integer> p2, Integer num) {
boolean b = p1.and(p2).test(num);
System.out.println("数字num:" + num + "是否大于100并且为偶数:" + b);
boolean b1 = p1.or(p2).test(num);
System.out.println("数字num:" + num + "是否大于100或者为偶数:" + b1);
boolean b2 = p1.negate().test(num);
System.out.println("数字num:" + num + "是否不大于100:" + b2);
boolean b3 = p2.negate().test(num);
System.out.println("数字num:" + num + "是否不为偶数:" + b3);
}
}
(5)Comparator接口--比较器接口:
比较器接口,用于比较指定元素值的大小。
Java
8版本中,添加了多个新的default
方法,用于比较器合并、反转等操作。
List<String> langList = Arrays.asList("Basic", "QBasic","HTML", "c", "c++", "PowerBuilder", "go", "Visual Basic", "c#","java");
// 按照ASCII码比较
Comparator<String> comparator1 = (s1, s2) -> {
return s1.compareTo(s2);
};
// 按照长度比较
Comparator<String> comparator2 = (s1, s2) -> {
return s1.length() - s2.length();
};
// 先比较长度,再比较ASCII码
Comparator<String> comparator3 = comparator2.thenComparing(comparator1);
// 在comparator3的基础上,反转条件
Comparator<String> comparator4 = comparator2.reversed();
// 按照指定Comparator,进行排序
langList.sort(comparator2);
三、Stream流:
java.util.Stream
表示能应用在一组元素上一次执行的操作序列。Stream
操作分为中间操作或者最终操作两种,最终操作返回一特定类型的计算结果,而中间操作返回Stream
本身,可以连续完成多个操作。
1、使用Stream流处理集合数据:
当我们需要对集合中的元素进行操作的时候,除了必需的添加、删除、获取外,最典型的就是集合遍历。我们来体验 集合操作数据的弊端,需求如下:
package com.yuan.stream;
import java.util.ArrayList;
import java.util.Collections;
public class Demo01 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张无忌", "周芷若", "赵敏", "张强", "张三丰");
// 1.拿到所有姓张的
ArrayList<String> zhanglist = new ArrayList<String>();
for (String string : list) {
if (string.startsWith("张")) {
zhanglist.add(string);
}
}
ArrayList<String> threeList = new ArrayList<String>();
// 2.拿到名字长度为3的字
for (String string : zhanglist) {
if (string.length() == 3) {
threeList.add(string);
}
}
System.out.println(threeList);
//使用stream 流
list.stream().filter(s1->s1.charAt(0)=='张').filter(s1->s1.length()==3).forEach(s1-> System.out.println(s1));
}
}
2、获取Stream流的两种方式:
java.util.stream.Stream<T>是JDK 8新加入的流接口。 获取一个流非常简单,有以下几种常用的方式:
-
Collection集合提供了 default Stream<E> stream()获取流;
-
Stream接口的静态方法 of 可以获取对应的流。
package com.yuan.stream;
import java.sql.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.stream.Stream;
//Stream 流的获取方式
//1、Collection 集合提供了default Stream<E> stream()获取流
//2、Stream 接口的静态方法of可以获取对应的流
public class Demo02 {
public static void main(String[] args) {
//方式一: Stream 的静态方法of
Stream<String> s1 = Stream.of("aa", "bb", "cc");
System.out.println(s1);
String[] arr={"aa", "bb", "cc"};
Stream<String> s2 = (Stream<String>) Stream.of(arr);
System.out.println(s2);
int[] numbers={1,2,3,4};
Stream<int[]> s3 = Stream.of(numbers);
System.out.println(s3);
//方式二: Collection 接口中Stream方法
List<String> list = Arrays.asList("aa", "bb", "cc");
Stream<String> s4 = list.stream();
System.out.println(s4);
HashSet<String> set = new HashSet<>(list);
Stream<String> s5 = set.stream();
System.out.println(s5);
HashMap<String, Integer> map = new HashMap<>();
System.out.println(map.entrySet().stream());
}
}
3、Stream 流的常用方法:
Stream流模型的操作很丰富,这里介绍一些常用的API。
这些方法可以被分成两种:
终结方法:返回值类型不再是 Stream类型的方法,不再支持链式调用。本小节中,终结方法包括 count和 forEach 方法。
非终结方法:返回值类型仍然是 Stream类型的方法,支持链式调用。(除了终结方法外,其余方法均为非终结 方法。)
(1)forEach() :遍历流中的元素
(2)count():Stream 流提供的count方法,统计其中的元素个数
(3)filter(): 用于锅炉数据,返回符合条件的数据
(4)limit()方法: 可以对流的元素进行截取前几个
(5)skip()方法: 跳过前几个元素,可以使用skip方法获取一个截取之后的新的集合
package com.yuan.method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
public class Demo01 {
public static void main(String[] args) {
List<String> list=new ArrayList<>();
Collections.addAll(list,"迪丽热巴","陶白白","吴磊","易烊千玺","刘亦菲");
//1、forEach() 获取流,遍历集合中的元素
Stream<String> s1 = list.stream();
s1.forEach(System.out::println);
//2、count():Stream 流提供的count方法,统计其中的元素个数
Stream<String> s2 = list.stream();
long count = s2.count();
System.out.println(count);
//3、filter(): 用于锅炉数据,返回符合条件的数据
list.stream().filter(str->str.length()==3).forEach(System.out::println);
System.out.println("=========================");
//4、limit()方法: 可以对流的元素进行截取前几个
list.stream().limit(2).forEach(str-> System.out.print(str+" "));
System.out.println();
System.out.println("===============");
//5、skip()方法: 跳过前几个元素,可以使用skip方法获取一个截取之后的新的集合
list.stream().skip(0).forEach(str-> System.out.print(str+" "));
}
}
(6)map() 可以将一种类型转换成另一种类型
(7)sorted()方法可以默认泛型排序,也可以自定义排序规则
(8)match()如果需要判断数据是否匹配指定的条件。可以使用match方法
(8.1)allMatch()判断所有元素是否满足条件
(8.2)anyMatch() 只要有一个满足条件就返回true
(8.3)noneMatch()所有的元素都不满足,返回true
package com.yuan.method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Stream;
public class Demo02 {
public static void main(String[] args) {
ArrayList<String> list=new ArrayList<>(Arrays.asList("32","22","45","11","33"));
Stream<String> s1 = list.stream();
//6、map() 可以将一种类型转换成另一种类型
Stream<Integer> s2 = s1.map(str -> Integer.parseInt(str));
// s2.forEach(number-> System.out.println(number));
System.out.println("==========sorted=========");
//如果满要将数据排序、可以使用 sorted方法
//使用泛型类型的默认排序规则排序
// s2.sorted().forEach(number-> System.out.println(number))
//使用自定义的Comparator比较规则排序
s2.sorted((a,b)->b-a).forEach(number-> System.out.println(number));
System.out.println("==========distinct=========");
Stream.of(1,3,2,1,3,4,5,6).distinct().forEach(System.out::println);
System.out.println("==========match=========");
//如果需要哦按段数据是否匹配指定的条件。可以使用match方法
//判断所有的元素是否满足条件
boolean b1 = Stream.of(1, 3, 2, 1, 3, 4, 5, 6).allMatch(number -> number > 0);
System.out.println("allmatch: "+b1);
//只要有一个满足条件就返回true || or
boolean b2 = Stream.of(1, 3, 2, 1, 3, 4, 5, 6).anyMatch(number -> number > 5);
System.out.println("anymatch: "+b2);
//所有的元素都不匹配,返回true
boolean b3 = Stream.of(1, 3, 2, 1, 3, 4, 5, 6).noneMatch(number -> number > 100);
System.out.println("nonematch: "+b3);
}
}
(9)collect() 方:法收集是一个 最终操作,返回Stream
中元素集合,返回值类型是集合(List、Set、Map)或 字符串。
Collectors.toList():转成List集合
Collectors.toSet():转成Set集合
Collectors.toMap():转成map集合
Collectors.groupingBy() :可以按照指定内容进行统计
Collectors.mapping():将一种数据类型的集合映射成另一种数据类型
package com.yuan.method;
import java.util.*;
import java.util.stream.Collectors;
public class Demo03 {
public static void main(String[] args) {
List<String> langList = Arrays.asList("abc", "deft", "gbhk", "bac", "fgh");
//将结果过滤,收集至List集合
List<String> list = langList.stream().filter(str -> str.toUpperCase().contains("B")).collect(
Collectors.toList()
);
System.out.println(list);
//将过滤结果收集到Set集合
Set<String> set = langList.stream().filter(str -> str.toUpperCase().contains("B")).collect(
Collectors.toSet()
);
System.out.println(set);
//将过滤结果收集到map集合
Map<String, Integer> map = langList.stream().distinct().filter(s -> s.toUpperCase().contains("B")).collect(
Collectors.toMap(s -> s, s -> s.length())
);
System.out.println(map);
//按照字符串的长度统计
Map<Integer, List<String>> groupMap = langList.stream().collect(
Collectors.groupingBy(str -> str.length())
);
System.out.println(groupMap);
//按照字符串长度转成集合
List<Integer> mappingList = langList.stream().collect(
Collectors.mapping(str -> str.length(), Collectors.toList())
);
System.out.println(mappingList);
}
}
4、Parallel Stream 并行流:
Stream
有串行和并行两种,串行Stream
上的操作是在一个线程中依次完成,而并行Stream
则是在多个线程上同时执行。
int max = 1000000;
List<String> values = new ArrayList<>(max);
for (int i = 0; i < max; i++) {
UUID uuid = UUID.randomUUID();
values.add(uuid.toString());
}
//串行排序
long t0 = System.nanoTime();//返回豪微秒
long count = values.stream().sorted().count();
System.out.println(count);long t1 = System.nanoTime();
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("串行排序,耗时共计: %d 毫秒", millis));
//并行排序
long t0 = System.nanoTime();
long count = values.parallelStream().sorted().count();
System.out.println(count);long t1 = System.nanoTime();
long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
System.out.println(String.format("并行排序,耗时共计: %d 毫秒", millis));
并行的执行效率高,但是不安全,在使用时要注意线程安全,