记录:292
场景:Stream流操作基本步骤一般归纳为:Stream流的创建、Stream流的中间操作、Stream流的终止操作。以数据源List为例,先把List<E>转换为Stream<E>;再对Stream<E>进行中间操作,比如使用Stream的filter函数筛选;最后使用Stream的forEach遍历输出结果。
版本:
JDK 1.8
Spring Boot 2.6.3
一、基础
1.函数式接口
(1)使用@FunctionalInterface注解标记的接口,接口中有且只有一个抽象方法。
(2)接口中的默认方法、静态方法等不计入抽象方法。
(3)JDK 1.8及其后续版本。
(4)函数入参中使用函数式接口,本质就是重写函数式接口中的抽象方法。
(5)函数入参中有函数式接口定义的参数是,使用Lambda表达式或者匿名类实现抽象方法是常用的方式。
(6)Stream流式编程中的API中大量使用了函数式接口作为入参。
2.Lambda 表达式
Lambda表达式,是Java 8 发布的重要特性。
Lambda允许把函数作为一个方法的参数,即函数作为参数传递进方法中。
Lambda表达式是代码变得更加简洁和紧凑。
Lambda表达式语法规则:
#方式一:
(parameters) -> expression
#方式二:
(parameters) ->{ expression; }
3.对<? super T>和<? extends R>理解
对<? super T>和<? extends R>理解,就是对泛型的理解。
3.1 概念理解
<? super T>:表示?匹配的类型都是T的父类,包括T本身。
<? extends R>:表示?匹配的类型都是类型R的子类,包括R本身
3.2 使用List协助理解
3.2.1 List<? super T>
List<? super T> list:表示集合中存放的都是T的父类(包括T本身)。
针对变量List<? super T> list。
(1)对List做添加(add(T))操作,必须使用T或者T的子类添加到list中。
(2)对List做遍历查询操作,必须使用T父类去遍历list,取出元素。
小结:拿到一个变量使用? super T修饰时,应该是对该变量做添加操作,不做查询操作。这种方式修饰叫做put原则。
3.2.2 List<? extends R>
List<? extends R> list:表示集合中存放的都是R的子类(包括R本身)。
针对变量List<? extends R> list。
(1)对List做添加(add(R))操作,必须使用R或者R的子类添加到list中。
(2)对List做遍历查询操作,必须使用R遍历list,取出元素.
小结:拿到一个变量使用? extends R修饰时,应该是对该变量做查询或取元素操作,不做添加操作。这种方式修饰叫做get原则。
二、Stream基础
1.Stream接口位置
(1)在jdk中,java.util.stream包下,存放的都是Stream相关的接口和实现类。
(2)在jdk中,Stream路径:java.util.stream.Stream。
Stream是interface类型,继承BaseStream和AutoCloseable接口。
BaseStream路径:java.util.stream.BaseStream。
AutoCloseable路径:java.lang.AutoCloseable
2.Stream理解
Stream,基于lambda表达式,是对集合对象功能的增强,以一种声明的方式处理数据。可以执行过滤、映射数据、查找、聚合等操作。
3.Stream操作
Stream的操作,一般归纳为3个步骤。
3.1 Stream流的创建
要操作流,需获取流,可以从集合、数组、或者Stream的静态方法创建流。
比如:
(1)java.util.Collection的Stream<E> stream()方法,那么实现Collection接口的类均可获取流。比如:java.util.List的实现类;java.util.Set的实现类;Map转换为流使用Map的entrySet等方法,这些方法返回值是Set。
(2)java.util.Arrays的stream方法,可以把数组转换为Stream。而且Arrays工具类重载了各种型式的stream方法,可以满足大部分从数组转换为Stream的需求。
(3)Stream的静态方法创建Stream流,比如of方法。
3.2 Stream流的中间操作
操作Stream流,比如filter过滤操作、map一个流转换为另一个流程、sorted排序、distinct去重等操作。
3.3 Stream流的终止操作
Stream流的终止操作后,可以从流中生成结果,其结果可以是任何不是流的值。比如forEach遍历结果、collect转换为其它型类型式。
4.stream包的几个Stream接口
java.util.stream包的几个Stream接口。Stream、IntStream、LongStream、DoubleStream接口都继承BaseStream。
java.util.stream.BaseStream
java.util.stream.Stream
java.util.stream.IntStream
java.util.stream.LongStream
java.util.stream.DoubleStream
三、Stream应用
本例根据操作Stream的3个基本步骤,把函数分为3类,在逐个应用。
1.应用Stream流的创建函数
应用Stream流的创建方式,使用这些函数可以从数据源获取Stream流。
1.1 操作场景
操作场景,就是函数功能。
(1)使用List获取Stream流。
(2)使用Map获取Stream流。
(3)使用List获取Stream流。
(4)使用List获取Stream流。
(5)使用Stream.of获取Stream流
(6)使用Stream.Builder获取Stream流。
(7)使用Stream.generate获取Stream流。
(8)使用Stream.iterate获取Stream流。
(9)使用Stream.concat合并两个流。
(10)使用Stream.empty获取空流。
1.2 操作实例
操作实例,就是函数应用。
/**
* 1.1使用List获取Stream流
*/
public static void f1_1() {
// 1.获取数据(List)
List<GirlVo> list = getList();
// 2.获取Stream流(使用List)
Stream<GirlVo> stream = list.stream();
// 3.遍历Stream流
stream.forEach(girlVo -> {
System.out.println(girlVo.toString());
});
}
/**
* 1.2使用Map获取Stream流
*/
public static void f1_2() {
// 1.获取数据(Map)
Map<String, Object> map = getMap();
// 2.获取Stream流(使用Map)
Stream<Map.Entry<String, Object>> stream = map.entrySet().stream();
// 3.遍历Stream流
stream.forEach(girlVo -> System.out.println(girlVo.toString()));
}
/**
* 1.3使用List获取Stream流
*/
public static void f1_3() {
// 1.获取数据(set)
Set<GirlVo> list = getSet();
// 2.获取Stream流(使用set)
Stream<GirlVo> stream = list.stream();
// 3.遍历Stream流
stream.forEach(girlVo -> {
System.out.println(girlVo.toString());
});
}
/**
* 1.4使用List获取Stream流
*/
public static void f1_4() {
// 1.获取数据(数组)
String[] cityArray = new String[]{"厦门", "杭州", "苏州", "北京"};
// 2.获取Stream流(使用数组)
Stream<String> stream = Arrays.stream(cityArray);
// 3.遍历Stream流
stream.forEach(System.out::println);
}
/**
* 1.5使用Stream.of获取Stream流
*/
public static void f1_5() {
// 1.使用Stream.of获取Stream流(单个元素)
Stream<String> stream01 = Stream.of("杭州");
// 2.使用Stream.of获取Stream流
Stream<String> stream02 = Stream.of("北京", "杭州", "厦门", "苏州");
stream02.forEach(System.out::println);
}
/**
* 1.6使用Stream.Builder获取Stream流
*/
public static void f1_6() {
// 1.创建Builder
Stream.Builder<Object> builder = Stream.builder();
// 2.添加元素
builder.add("北京");
builder.add("苏州");
// 3.创建Stream
Stream<Object> stream = builder.build();
// 4.遍历Stream
stream.forEach(System.out::println);
}
/**
* 1.7使用Stream.generate获取Stream流
*/
public static void f1_7() {
Stream<Double> stream04 = Stream.generate(Math::random);
stream04.forEach(num -> System.out.println("generate: " + num));
}
/**
* 1.8使用Stream.iterate获取Stream流
*/
public static void f1_8() {
Stream<Long> stream05 = Stream.iterate(30L, ele -> (ele + 2));
stream05.forEach(num -> System.out.println("iterate: " + num));
}
/**
* 1.9 使用Stream.concat合并两个流
*/
public static void f1_9() {
// 1.使用Stream.of获取Stream流
Stream<String> stream0401 = Stream.of("北京", "杭州");
Stream<String> stream0402 = Stream.of("厦门", "苏州");
// 2.使用Stream.concat合并两个流
Stream<String> stream04 = Stream.concat(stream0401, stream0402);
stream04.forEach(num -> System.out.println("合并流: " + num));
}
/**
* 1.10 使用Stream.empty获取空流
*/
public static void f1_10() {
// 1.使用Stream.empty获取空流
Stream<GirlVo> stream01 = Stream.empty();
}
2.应用Stream流的中间操作函数
应用Stream流的中间操作函数,使用这些函数对Stream流进行操作,操作的结果还是Stream流。
2.1 操作场景
操作场景,就是函数功能。
(1)应用Stream的filter,做过滤筛选操作。
(2)应用Stream的map,把Stream<GirlVo>转换为Stream<Object>。
(3)应用Stream的mapToInt,把Stream<GirlVo>转换为IntStream。
(4)应用Stream的mapToLong,把Stream<GirlVo>转换为LongStream。
(5)应用Stream的mapToDouble,把Stream<GirlVo>转换为DoubleStream。
(6)应用Stream的flatMap,把List<List<GirlVo>>转换为Stream<GirlVo>。
(7)应用Stream的flatMapToInt,把List<List<GirlVo>>转换为IntStream。
(8)应用Stream的flatMapToLong,把List<List<GirlVo>>转换为LongStream。
(9)应用Stream的flatMapToDouble,把List<List<GirlVo>>转换为DoubleStream。
(10)应用Stream的distinct去重。
(11)应用Stream的sorted排序。
(12)应用Stream的sorted排序。
(13)应用Stream的peek调试。
(14)应用Stream的limit,限制数量。
(15)应用Stream的skip,跳过指定个数元素。
2.2 操作实例
操作实例,就是函数应用。
/**
* 2.1 应用Stream的filter,做过滤筛选操作
* 案例: 找出B罩杯,年龄最小的女孩.
*/
public static void f2_1() {
// 1.获取数据(List)
List<GirlVo> list = getList();
// 2.获取Stream流(使用List)
Stream<GirlVo> stream = list.stream();
// 3.Stream的filter的使用
OptionalLong optionalLong = stream.filter(girlVo -> Objects.equals(
girlVo.getCupSize(), "B"))
.mapToLong(GirlVo::getAge).min();
// 4.获取结果
if (optionalLong.isPresent()) {
System.out.println("B罩杯,年龄最小的女孩: " + optionalLong.getAsLong());
}
}
/**
* 2.2 应用Stream的map
* 案例: 把Stream<GirlVo>转换为Stream<Object>
*/
public static void f2_2() {
// 1.获取数据(List)
List<GirlVo> list = getList();
// 2.获取Stream流(使用List)
Stream<GirlVo> stream = list.stream();
// 3.Stream<GirlVo>转换为Stream<Object>
Stream<Object> objStream = stream.map(girlVo -> {
Object obj = girlVo.getGirlName();
return obj;
});
// 4.遍历结果
objStream.forEach(obj -> {
System.out.println("Girl的名称: " + obj.toString());
});
}
/**
* 2.3 应用Stream的mapToInt
* 案例: 把Stream<GirlVo>转换为IntStream
*/
public static void f2_3() {
// 1.获取数据(List)
List<GirlVo> list = getList();
// 2.获取Stream流(使用List)
Stream<GirlVo> stream = list.stream();
// 3.Stream<GirlVo>转换为IntStream
IntStream intStream = stream.mapToInt(girlVo -> {
int girlId = Integer.parseInt(girlVo.getGirlId());
return girlId;
});
// 4.遍历结果
intStream.forEach(girlId -> {
System.out.println("Girl的ID: " + girlId);
});
}
/**
* 2.4 应用Stream的mapToLong
* 案例: 把Stream<GirlVo>转换为LongStream
*/
public static void f2_4() {
// 1.获取数据(List)
List<GirlVo> list = getList();
// 2.获取Stream流(使用List)
Stream<GirlVo> stream = list.stream();
// 3.Stream<GirlVo>转换为LongStream
LongStream longStream = stream.mapToLong(girlVo -> {
long girlId = girlVo.getAge();
return girlId;
});
// 4.使用LongStream的average求平均值
OptionalDouble opt = longStream.average();
if (opt.isPresent()) {
System.out.println("Girl的平均年龄: " + opt.getAsDouble());
}
}
/**
* 2.5 应用Stream的mapToDouble
* 案例: 把Stream<GirlVo>转换为DoubleStream
*/
public static void f2_5() {
// 1.获取数据(List)
List<GirlVo> list = getList();
// 2.获取Stream流(使用List)
Stream<GirlVo> stream = list.stream();
// 3.Stream<GirlVo>转换为DoubleStream
DoubleStream doubleStream = stream.mapToDouble(girlVo -> {
double height = girlVo.getHeight();
return height;
});
// 4.使用DoubleStream的max求最大值
OptionalDouble opt = doubleStream.max();
if (opt.isPresent()) {
System.out.println("身高最高的girl身高: " + opt.getAsDouble());
}
}
/**
* 2.6 应用Stream的flatMap
* 案例: 把List<List<GirlVo>>转换为Stream<GirlVo>
*/
public static void f2_6() {
// 1.获取数据(List<List<GirlVo>>)
List<List<GirlVo>> list = getMultiList();
// 2.List<List<GirlVo>>转换为Stream<GirlVo>
Stream<GirlVo> stream = list.stream().flatMap(mapper -> {
return mapper.stream();
});
// 3.遍历结果
stream.forEach(obj -> {
System.out.println("遍历信息: " + obj.toString());
});
}
/**
* 2.7 应用Stream的flatMapToInt
* 案例: 把List<List<GirlVo>>转换为IntStream
*/
public static void f2_7() {
// 1.获取数据(List<List<GirlVo>>)
List<List<GirlVo>> list = getMultiList();
// 2.List<List<GirlVo>>转换为IntStream
IntStream stream = list.stream().flatMapToInt(mapper -> {
Stream<GirlVo> girlStream = mapper.stream();
return girlStream.mapToInt(girl -> {
return (int) girl.getAge();
});
});
// 3.遍历结果
stream.forEach(age -> {
System.out.println("年龄: " + age);
});
}
/**
* 2.8 应用Stream的flatMapToLong
* 案例: 把List<List<GirlVo>>转换为LongStream
* 相当于: 把List<List<GirlVo>>循环遍历2次直接在Stream中完成
*/
public static void f2_8() {
// 1.获取数据(List<List<GirlVo>>)
List<List<GirlVo>> list = getMultiList();
// 2.List<List<GirlVo>>转换为LongStream
LongStream stream = list.stream().flatMapToLong(mapper -> {
Stream<GirlVo> girlStream = mapper.stream();
return girlStream.mapToLong(girl -> Long.parseLong(girl.getGirlId()));
});
// 3.遍历结果
stream.forEach(age -> {
System.out.println("年龄: " + age);
});
}
/**
* 2.9 应用Stream的flatMapToDouble
* 案例: 把List<List<GirlVo>>转换为DoubleStream
*/
public static void f2_9() {
// 1.获取数据(List<List<GirlVo>>)
List<List<GirlVo>> list = getMultiList();
// 2.List<List<GirlVo>>转换为LongStream
DoubleStream stream = list.stream().flatMapToDouble(mapper -> {
Stream<GirlVo> girlStream = mapper.stream();
// Lambda表达式写法
return girlStream.mapToDouble(GirlVo::getHeight);
});
// 3.遍历结果
stream.forEach(height -> {
System.out.println("身高: " + height);
});
}
/**
* 2.10 应用Stream的distinct去重
* 案例: 应用Stream的distinct去重
* 原理: 去重根据Object.equals(Object)判断
* Girl01是从写了equals(Object obj)和 hashCode(),去重效果才会生效
*/
public static void f2_10() {
// 1.获取数据(List)
List<Girl01> list = getList01();
// 2.获取Stream流(使用List)
Stream<Girl01> stream01 = list.stream();
// 3.使用distinct去重
Stream<Girl01> stream02 = stream01.distinct();
// 4.遍历结果
stream02.forEach(Girl01 -> {
System.out.println("Girl信息: " + Girl01);
});
}
/**
* 2.11 应用Stream的sorted排序
* 案例: 应用Stream的sorted排序
*/
public static void f2_11() {
// 1.获取数据(List)
List<GirlVo> list = getList();
// 2.获取Stream流(使用List)
Stream<GirlVo> stream01 = list.stream();
// 3.使用sorted排序
Stream<Long> stream02 = stream01.map(GirlVo::getAge).sorted();
// 4.遍历结果
stream02.forEach(girl -> {
System.out.println("Girl年龄: " + girl);
});
}
/**
* 2.12 应用Stream的sorted排序
* 案例: 应用Stream的sorted排序
*/
public static void f2_12() {
// 1.获取数据(List)
List<GirlVo> list = getList();
// 2.获取Stream流(使用List)
Stream<GirlVo> stream01 = list.stream();
// 3.使用sorted排序 int compare(T o1, T o2);o1-o2代表正序排序,o2-o1代表倒序排序
Stream<GirlVo> stream02 = stream01.sorted((girl01, girl02) -> {
return (int) (girl01.getAge() - girl02.getAge());
});
// 4.遍历结果
stream02.forEach(girl -> {
System.out.println("Girl信息: " + girl);
});
}
/**
* 2.13 应用Stream的peek调试
* 案例: 应用Stream的peek对流操作中的流水线进行调试
*/
public static void f2_13() {
// 1.获取数据(List)
List<GirlVo> list = getList();
// 2.应用Stream的peek记录调试过程
Stream<GirlVo> stream01 = list.stream().peek(girlVo -> {
System.out.println("首次peek: " + girlVo);
}).filter(girlVo -> girlVo.getAge() > 25)
.peek(girlVo -> {
System.out.println("filter后peek: " + girlVo);
}).sorted((girl01, girl02) -> {
return (int) (girl01.getAge() - girl02.getAge());
}).peek(girlVo -> {
System.out.println("sorted后peek: " + girlVo);
});
// 3.遍历结果
stream01.forEach(girl -> {
System.out.println("forEach遍历girl信息: " + girl);
});
}
/**
* 2.14 应用Stream的limit,限制数量
* 案例: 应用Stream的limit,限制数量
*/
public static void f2_14() {
// 1.获取数据(List)
List<GirlVo> list01 = getList();
// 2.获取Stream流(使用List)
Stream<GirlVo> stream01 = list01.stream();
// 3.应用Stream的limit
List<GirlVo> list0101 = stream01.limit(2).collect(Collectors.toList());
}
/**
* 2.15 应用Stream的skip,跳过指定个数元素
* 案例: 应用Stream的skip,跳过指定个数元素
*/
public static void f2_15() {
// 1.获取数据(List)
List<GirlVo> list02 = getList();
// 2.获取Stream流(使用List)
Stream<GirlVo> stream02 = list02.stream();
// 3.应用Stream的skip
List<GirlVo> list0201 = stream02.skip(2).collect(Collectors.toList());
}
3.应用Stream流的终止操作函数
应用Stream流的终止操作函数,使用这些函数对Stream流进行操作后,生成结果不是Stream流了,而是一个期待类型的结果值。
3.1 操作场景
操作场景,就是函数功能。
(1)应用Stream的forEach和forEachOrdered遍历结果。
(2)应用Stream的toArray将流转换为数组。
(3)应用Stream的reduce,做累加操作。
(4)应用Stream的collect,将流转换为集合。
(5)应用Stream的collect,将流转换为连续字符串。
(6)应用Stream的collect,将流转换为List集合。
(7)应用Stream的collect,对流做分组操作,转换为Map<String, List<GirlVo>>。
(8)应用Stream的collect,对流做分组操作,转换为Map<String, Map<Long, List<GirlVo>>>。
(9)应用Stream的min,找到最小值。
(10)应用Stream的max,找到最大值。
(11)应用Stream的count,找到元素个数。
(12)应用Stream的anyMatch,有一个匹配则true。
(13)应用Stream的allMatch,全部匹配则true。
(14)应用Stream的noneMatch,不存在则true。
(15)应用Stream的findFirst,找到第一个元素。
(16)应用Stream的findAny,找到任意一个元素。
3.2 操作实例
操作实例,就是函数应用。
/**
* 3.1 应用Stream的forEach遍历结果
* 案例: 应用Stream的forEach和forEachOrdered
*/
public static void f3_1() {
// 1.1 获取数据(List)
List<GirlVo> list03 = getList();
// 1.2 获取Stream流(使用List)
Stream<GirlVo> stream03 = list03.stream();
// 1.3 使用forEach遍历结果
stream03.forEach(girlVo -> System.out.println("girl信息: " + girlVo));
// 2.1 获取数据(List)
List<GirlVo> list04 = getList();
// 2.2 获取Stream流(使用List)
Stream<GirlVo> stream04 = list04.stream();
// 2.3 使用forEachOrdered遍历结果
stream04.forEachOrdered(girlVo -> System.out.println("girl信息Ordered: " + girlVo));
}
/**
* 3.2 应用Stream的toArray
* 案例: 应用Stream的toArray将流转换为数组
*/
public static void f3_2() {
// 1.1 获取数据(List)
List<GirlVo> list05 = getList();
// 1.2 获取Stream流(使用List)
Stream<GirlVo> stream05 = list05.stream();
// 1.3 应用toArray将Stream流转换为数组
Object[] objs = stream05.toArray();
// 2.1 获取数据(List)
List<GirlVo> list06 = getList();
// 2.2 获取Stream流(使用List)
Stream<GirlVo> stream06 = list06.stream();
// 2.3 应用toArray将Stream流转换为数组
Object[] objs2 = stream06.toArray(GirlVo[]::new);
}
/**
* 3.3 应用Stream的reduce
* 案例: 应用Stream的reduce,做累加操作
*/
public static void f3_3() {
// 1.1 获取数据(List)
List<GirlVo> list01 = getList();
// 1.2.获取Stream流(使用List)
LongStream stream01 = list01.stream().mapToLong(GirlVo::getAge);
// 1.3 应用reduce求和操作
OptionalLong opt01 = stream01.reduce((a, b) -> a + b);
if (opt01.isPresent()) {
System.out.println("输出值: " + opt01.getAsLong());
}
// 2.1 获取数据(List)
List<GirlVo> list02 = getList();
// 2.2.获取Stream流(使用List)
LongStream stream02 = list02.stream().mapToLong(GirlVo::getAge);
// 2.3 应用reduce求和操作
long opt02 = stream02.reduce(100, (a, b) -> a + b);
System.out.println("输出值: " + opt02);
// 3.1 获取Stream流(Stream.of)
Stream<Integer> stream = Stream.of(100, 200, 300, 400);
// 3.2 应用reduce求和操作
Integer result = stream.reduce(0, Integer::sum, Integer::sum);
System.out.println("result" + result);
}
/**
* 3.4 应用Stream的collect
* 案例: 应用Stream的collect,将流转换为集合
*/
public static void f3_4() {
// 1.获取Stream流(Stream.of)
Stream<String> stringStream0101 = Stream.of("北京", "杭州", "厦门", "苏州");
// 2.应用Stream的collect,将流转换为集合
List<String> asList0101 = stringStream0101.collect(ArrayList::new, ArrayList::add,
ArrayList::addAll);
System.out.println("asList0101: " + asList0101);
}
/**
* 3.5 应用Stream的collect
* 案例: 应用Stream的collect,将流转换为连续字符串
*/
public static void f3_5() {
// 1.获取Stream流(Stream.of)
Stream<String> stringStream02 = Stream.of("北京,", "杭州,", "厦门,", "苏州,", "是不错的城市.");
// 2.应用Stream的collect,将流转换为连续字符串
String concat = stringStream02.collect(StringBuilder::new, StringBuilder::append,
StringBuilder::append).toString();
System.out.println("concat: " + concat);
}
/**
* 3.6 应用Stream的collect
* 案例: 应用Stream的collect,将流转换为List集合
*/
public static void f3_6() {
// 1.获取Stream流(Stream.of)
Stream<String> stringStream0201 = Stream.of("北京", "杭州", "郑州", "厦门", "苏州");
// 2.应用Stream的collect,将流转换为List
List<String> asList0201 = stringStream0201.collect(Collectors.toList());
System.out.println("asList0201: " + asList0201);
}
/**
* 3.7 应用Stream的collect
* 案例: 应用Stream的collect,对流做分组操作,转换为Map<String, List<GirlVo>>
*/
public static void f3_7() {
// 1.获取Stream流(Stream.of)
Stream<GirlVo> girlStream0201 = getList().stream();
// 2.应用Stream的collect,将流分组转换为Map<String, List<GirlVo>>
Map<String, List<GirlVo>> girlByCupSize = girlStream0201.collect(Collectors.groupingBy(GirlVo::getCupSize));
System.out.println("girlByCupSize: " + girlByCupSize);
}
/**
* 3.8 应用Stream的collect
* 案例: 应用Stream的collect,对流做分组操作,转换为Map<String, Map<Long, List<GirlVo>>>
*/
public static void f3_8() {
// 1.获取Stream流(使用List)
Stream<GirlVo> girlStream0202 = getList().stream();
// 2.应用Stream的collect,对流做分组操作,转换为Map<String, Map<Long, List<GirlVo>>>
Map<String, Map<Long, List<GirlVo>>> girlByCupSizeAndAge
= girlStream0202.collect(Collectors.groupingBy(GirlVo::getCupSize,
Collectors.groupingBy(GirlVo::getAge)));
System.out.println("peopleByCupSizeAndAge: " + girlByCupSizeAndAge);
}
/**
* 3.9 应用Stream的min
* 案例: 应用Stream的min,找到最小值
*/
public static void f3_9() {
// 1.获取Stream流(Stream.of)
Stream<Long> stream01 = Stream.of(100L, 200L, 300L);
// 2.应用Stream的min,求最小值
Optional<Long> opt01 = stream01.min((o1, o2) -> (int) (o1 - o2));
// 3.获取结果
if (opt01.isPresent()) {
System.out.println("opt01: " + opt01);
}
}
/**
* 3.10 应用Stream的max
* 案例: 应用Stream的max,找到最大值
*/
public static void f3_10() {
// 1.获取Stream流(Stream.of)
Stream<Long> stream02 = Stream.of(100L, 200L, 300L);
// 2.应用Stream的max,求最小值
Optional<Long> opt02 = stream02.max((o1, o2) -> (int) (o1 - o2));
// 3.获取结果
if (opt02.isPresent()) {
System.out.println("opt02: " + opt02);
}
}
/**
* 3.11 应用Stream的count
* 案例: 应用Stream的count,找到元素个数
*/
public static void f3_11() {
// 1.获取Stream流(Stream.of)
Stream<Long> stream03 = Stream.of(100L, 200L, 300L);
// 2.应用Stream的count,求元素个数
long opt03 = stream03.count();
// 3.打印结果
System.out.println("opt03: " + opt03);
}
/**
* 3.12 应用Stream的anyMatch
* 案例: 应用Stream的anyMatch,有一个匹配则true
*/
public static void f3_12() {
// 1.获取Stream流(使用List)
Stream<GirlVo> girlStream01 = getList().stream();
// 2.应用Stream的anyMatch,有一个匹配则true
boolean result01 = girlStream01.anyMatch(girl -> Objects.equals(girl.getCupSize(), "B"));
// 3.打印结果
System.out.println("是否有B罩杯: " + result01);
}
/**
* 3.13 应用Stream的allMatch
* 案例: 应用Stream的allMatch,全部匹配则true
*/
public static void f3_13() {
// 1.获取Stream流(使用List)
Stream<GirlVo> girlStream02 = getList().stream();
// 2.应用Stream的anyMatch,全部匹配则true
boolean result02 = girlStream02.allMatch(girl -> Objects.equals(girl.getCupSize(), "B"));
// 3.打印结果
System.out.println("是否所有的都是B罩杯: " + result02);
}
/**
* 3.14 应用Stream的noneMatch
* 案例: 应用Stream的noneMatch,不存在则true
*/
public static void f3_14() {
// 1.获取Stream流(使用List)
Stream<GirlVo> girlStream03 = getList().stream();
// 2.应用Stream的anyMatch,不存在则true
boolean result03 = girlStream03.noneMatch(girl -> Objects.equals(girl.getCupSize(), "G"));
// 3.打印结果
System.out.println("是否所有的都是G罩杯: " + result03);
}
/**
* 3.15 应用Stream的findFirst
* 案例: 应用Stream的findFirst,找到第一个元素
*/
public static void f3_15() {
// 1.获取Stream流(使用List)
Stream<String> stringStream01 = Stream.of("北京", "杭州", "厦门", "苏州");
// 2.应用Stream的findFirst,找到第一个元素
Optional<String> opt01 = stringStream01.findFirst();
// 3.打印结果
opt01.ifPresent(city -> System.out.println("第一个: " + city));
}
/**
* 3.16 应用Stream的findAny
* 案例: 应用Stream的findAny,找到任意一个元素
*/
public static void f3_16() {
// 1.获取Stream流(使用List)
Stream<String> stringStream02 = Stream.of("北京", "杭州", "郑州", "厦门", "苏州");
// 2.应用Stream的findAny,找到任意一个元素
Optional<String> opt02 = stringStream02.findAny();
// 3.打印结果
opt02.ifPresent(city -> System.out.println("任意一个: " + city));
}
4.本例生成数据的函数和Java Bean对象
测试验证需要数据,生成辅助类和方法。
4.1 Java Bean对象
Java Bean对象,包括GirlVo和Girl01,主要使用GirlVo。Girl01在做去重时使用到,因为重写了基类Object的equals(Object obj)和 hashCode()。
(1)GirlVo
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class GirlVo {
/**ID号*/
String girlId;
/**姓名*/
String girlName;
/**年龄*/
long age;
/**身高*/
double height;
/**罩杯*/
String cupSize;
}
(2)Girl01
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Girl01 {
/**ID号*/
String girlId;
/**姓名*/
String girlName;
/**年龄*/
long age;
/**身高*/
double height;
/**罩杯*/
String cupSize;
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Girl01 var = (Girl01) obj;
return (Objects.equals(this.girlId, var.girlId));
}
@Override
public int hashCode() {
return Objects.hash(girlId);
}
}
4.2 生成数据的函数
生成数据的函数,包括以下几个。
(1)获取List数据,在List中存放GirlVo对象。
(2)获取Map数据,在Map中存放(key,value)对应(girlId,GirlVo)。
(3)获取Set数据,在Set中存放GirlVo对象。
(4)获取List<List<GirlVo>>。
(5)获取List数据,在List中存放Girl01对象。
/**
* 获取List数据,在List中存放GirlVo对象
*/
public static List<GirlVo> getList() {
List<GirlVo> list = new ArrayList<>();
GirlVo girl01 = GirlVo.builder().girlId("1001").girlName("张一").age(27).height(169).cupSize("F").build();
GirlVo girl02 = GirlVo.builder().girlId("1002").girlName("王二").age(29).height(175).cupSize("B").build();
GirlVo girl03 = GirlVo.builder().girlId("1003").girlName("刘五").age(24).height(160).cupSize("B").build();
GirlVo girl04 = GirlVo.builder().girlId("1004").girlName("陈六").age(21).height(168).cupSize("C").build();
GirlVo girl05 = GirlVo.builder().girlId("1005").girlName("赵七").age(25).height(169).cupSize("C").build();
GirlVo girl06 = GirlVo.builder().girlId("1006").girlName("张八").age(26).height(165).cupSize("A").build();
list.add(girl01);
list.add(girl02);
list.add(girl03);
list.add(girl04);
list.add(girl05);
list.add(girl06);
return list;
}
/**
* 获取Map数据,在Map中存放(key,value)对应(girlId,GirlVo)
*/
public static Map<String, Object> getMap() {
Map<String, Object> map = new HashMap<>();
List<GirlVo> list = getList();
Stream<GirlVo> stream = list.stream();
stream.forEach(girlVo -> {
map.put(girlVo.getGirlId(), girlVo);
});
return map;
}
/**
* 获取Set数据,在Set中存放GirlVo对象
*/
public static Set<GirlVo> getSet() {
Set<GirlVo> set = new HashSet<>();
List<GirlVo> list = getList();
Stream<GirlVo> stream = list.stream();
stream.forEach(girlVo -> {
set.add(girlVo);
});
return set;
}
/**
* 获取List<List<GirlVo>>
*/
public static List<List<GirlVo>> getMultiList() {
List<GirlVo> list01 = new ArrayList<>();
List<GirlVo> list02 = new ArrayList<>();
List<List<GirlVo>> list = new ArrayList<>();
GirlVo girl01 = GirlVo.builder().girlId("1001").girlName("张一").age(27).height(169).cupSize("F").build();
GirlVo girl02 = GirlVo.builder().girlId("1002").girlName("王二").age(29).height(175).cupSize("B").build();
GirlVo girl03 = GirlVo.builder().girlId("1003").girlName("刘五").age(24).height(160).cupSize("B").build();
GirlVo girl04 = GirlVo.builder().girlId("1004").girlName("陈六").age(21).height(168).cupSize("C").build();
GirlVo girl05 = GirlVo.builder().girlId("1005").girlName("赵七").age(25).height(169).cupSize("C").build();
GirlVo girl06 = GirlVo.builder().girlId("1006").girlName("张八").age(26).height(165).cupSize("A").build();
list01.add(girl01);
list01.add(girl02);
list01.add(girl03);
list02.add(girl04);
list02.add(girl05);
list02.add(girl06);
list.add(list01);
list.add(list02);
return list;
}
/**
* 获取List数据,在List中存放Girl01对象
* Girl01是重写了equals(Object obj)和 hashCode()
* 在使用distinct时去重根据重写规则判断
*/
public static List<Girl01> getList01() {
List<Girl01> list = new ArrayList<>();
Girl01 girl01 = Girl01.builder().girlId("1001").girlName("张一").age(27).height(169).cupSize("F").build();
Girl01 girl02 = Girl01.builder().girlId("1002").girlName("王二").age(29).height(175).cupSize("B").build();
Girl01 girl03 = Girl01.builder().girlId("1003").girlName("刘五").age(24).height(160).cupSize("B").build();
Girl01 girl04 = Girl01.builder().girlId("1004").girlName("陈六").age(21).height(168).cupSize("C").build();
Girl01 girl05 = Girl01.builder().girlId("1005").girlName("赵七").age(25).height(169).cupSize("C").build();
Girl01 girl06 = Girl01.builder().girlId("1001").girlName("张一").age(27).height(169).cupSize("F").build();
list.add(girl01);
list.add(girl02);
list.add(girl03);
list.add(girl04);
list.add(girl05);
list.add(girl06);
return list;
}
四、小结
在研究API时,训练是一方面。归纳和分类有助于理解整体思路以及API应用场景。
以上,感谢。
2022年8月21日