1.java8两大亮点之Stream
stream直译为流,但它与原IO流完全不同的概念。
简单地说:它是数据的渠道,用于操作数据源所生成的元素的序列,它可以像数据库中的数据一样,使用sql去操作。
- stream自己不会存储元素
- stream不会改变源对象,只是返回一个新的stream。
-
Stream操作是延迟执行的,需要执行的时候才会去给出结果。
流式操作:创建Stream-中间操作-终止操作
/**
* 创建Stream
*/
@Test
public void test1() {
//1.Collection系列集合 Stream()串行和parallelStream()并行
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();
System.out.println(stream);
//2.Arrays中的静态方法stream()获取数组流
Student[] stus = new Student[10];
Stream<Student> stream2 = Arrays.stream(stus);
System.out.println(stream2);
//3.Stream类中的静态方法of()
Stream<String> stream3 = Stream.of("a", "b", "c");
System.out.println(stream3);
//4.无限流
Stream.iterate(0, (x) -> x + 1).limit(10).forEach(System.out::println);
//5.生成
Stream.generate(() ->((Math.random())*100)).limit(10).forEach(System.out::println);
}
输出结果:
java.util.stream.ReferencePipeline$Head@79be0360
java.util.stream.ReferencePipeline$Head@22a67b4
java.util.stream.ReferencePipeline$Head@57855c9a
88
6
55
67
91
17
91
9
6
14
(1)中间操作
(a)filter过滤,相当于sql中where age > 40
forEach(System.out::println)为终止操作,下面只是想看到操作结果
在forEach,其实没做任何操作,当执行到forEach终止操作才执行
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@ToString
@EqualsAndHashCode
public class Student {
private Integer stuId;
private String name;
private Integer age;
private Double matchScore;
public Student(String name) {
this.name = name;
}
}
/**
* filter过滤
*/
@Test
public void test1() {
stus.stream().filter(x -> x.getAge() > 40).forEach(System.out::println);
}
limit截断
/**
* limit截断
*/
@Test
public void test2(){
stus.stream().limit(2).forEach(System.out::println);
}
skip跳过
/**
* skip跳过
*/
@Test
public void test3(){
stus.stream().skip(2).forEach(System.out::println);
}
distinct去重
/**
* distinct去重
*/
@Test
public void test4() {
stus.stream().distinct().forEach(System.out::println);
}
(b)映射
map会转换成一个新对象
/**
* map映射
*/
@Test
public void test5() {
List<String> a = Arrays.asList("abc", "cba", "bca");
a.stream().map(x -> x.toUpperCase()).forEach(System.out::println);
stus.stream().map(Student::getStuId).forEach(System.out::print);
}
输出结果为:
ABC
CBA
BCA
112345
flatMap将多个流里元素加到同一个流中
@Test
public void test6() {
List<String> a = Arrays.asList("abc", "cba", "bca");
Stream<Stream<Character>> s = a.stream().map(TestLambda4::filterCharacter);
s.forEach(x -> {
x.forEach(System.out::println);
});
//直接使用flatMap
Stream<Character> s1 = a.stream().flatMap(TestLambda4::filterCharacter);
System.out.println("--------------------------");
s1.forEach(System.out::println);
}
public static Stream<Character> filterCharacter(String str) {
List<Character> list = new ArrayList<>();
for (Character c : str.toCharArray()) {
list.add(c);
}
return list.stream();
}
结果输出一样。
(c)排序
/**
* 排序
*/
@Test
public void test8() {
List<String> a = Arrays.asList("bb", "cc", "dd", "aa");
//自然排序(comparable)
a.stream().sorted().forEach(System.out::println);
//定制排序()
stus.stream().sorted((x, y) -> x.getMatchScore().compareTo(y.getMatchScore())).forEach(System.out::println);
}
(2)终止操作
(a)查找与匹配
获取数据
@Test
public void test1() {
//是否匹配所有元素返回true
boolean b1 = stus.stream().allMatch(x -> x.getAge() > 19);
System.out.println(b1);
//只要有一个匹配返回true
boolean b2 = stus.stream().anyMatch(x -> x.getAge() > 43);
System.out.println(b2);
//没有匹配所有元素(都不符合返回true)
boolean b3 = stus.stream().noneMatch(x -> x.getAge() > 43);
System.out.println(b3);
//取第一条,因为结果可能为空,可以用Optiona接,可以用方法get获取
Optional<Student> op1 = stus.stream().sorted((x, y) -> Double.compare(x.getMatchScore(), y.getMatchScore())).findFirst();
System.out.println(op1.get());
//随机取一条
Optional<Student> op2 = stus.parallelStream().findAny();
System.out.println(op2.get());
}
统计,与数据库中的聚合函数类似
@Test
public void test2() {
//相当于sql中count
Long num1 = stus.stream().count();
System.out.println(num1);
//max或者min一样
Optional<Student> op1 = stus.stream().max((x, y) -> Double.compare(x.getMatchScore(), y.getMatchScore()));
System.out.println(op1.get());
System.out.println(stus.stream().map(Student::getMatchScore).min(Double::compare).get());
}
(b)归约
/**
* 归约
* reduce(T identy, BinaryOperaator)/reduce(BinaryOperaator)
* 可以将流中元素反复结合起来,得到一个新的值
*/
@Test
public void test3() {
List<Integer> lis = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
//算总和
Integer sum = lis.stream().reduce(0, (x, y) -> x + y);
System.out.println(sum);
/**
* 统计总分
* 流行map-reduce模式,大数据里面
*/
Double sum1 = stus.stream().map(Student::getMatchScore).reduce(Double::sum).get();
System.out.println(sum1);
}
(c)收集
/**
* collect--将流转换成其他方式。接收一个Collector接口的实现,用于给stream中元素做汇总的方法
*/
@Test
public void test4() {
//
List<String> lis = stus.stream().map(Student::getName).collect(Collectors.toList());
lis.forEach(System.out::println);
HashSet<String> hs = stus.stream().map(Student::getName).collect(Collectors.toCollection(HashSet::new));
hs.forEach(System.out::println);
//会报错 Duplicate key 100.0,
Map<Integer, Double> hs2 = stus.stream().collect(Collectors.toMap(Student::getStuId, Student::getMatchScore));
Map<Integer, Student> hs1 = stus.stream().collect(Collectors.toMap(Student::getStuId, Function.identity(), (key1, key2) -> key2));
System.out.println(hs1);
}
(d)数据库中聚合函数操作
@Test
public void test5() {
//总数
Long count = stus.stream().collect(Collectors.counting());
System.out.println(count);
//平均值
Double avg = stus.stream().collect(Collectors.averagingDouble(Student::getMatchScore));
System.out.println(avg);
//总和
Double sum = stus.stream().collect(Collectors.summingDouble(Student::getMatchScore));
System.out.println(sum);
//最大值
Optional<Student> max = stus.stream().collect(Collectors.maxBy((x, y) -> Double.compare(x.getMatchScore(), y.getMatchScore())));
System.out.println(max.get().getMatchScore());
//最小值
Optional<Student> min = stus.stream().collect(Collectors.minBy((x, y) -> Double.compare(x.getMatchScore(), y.getMatchScore())));
System.out.println(min.get().getMatchScore());
//获取以上所有
DoubleSummaryStatistics dss = stus.stream().collect(Collectors.summarizingDouble(Student::getMatchScore));
}
(e)分组,分区以及字符串拼接
/**
* 分组
*/
@Test
public void test6() {
//根据年龄分组
Map<Integer, List<Student>> map = stus.stream().collect(Collectors.groupingBy(Student::getAge));
System.out.println(map);
//多级分组 先年龄分在按 分数分
Map<Integer, Map<String, List<Student>>> map1 = stus.stream().collect(Collectors.groupingBy(Student::getAge, Collectors.groupingBy(
(e) -> {
if (e.getMatchScore() > 80) {
return "优秀";
} else {
return "及格";
}
}
)));
System.out.println(map1);
//分区
Map<Boolean, List<Student>> map2 = stus.stream().collect(Collectors.partitioningBy(e -> e.getMatchScore() > 80));
System.out.println(map2);
//文件拼接,常用于文件的拼接
String s = stus.stream().map(x -> x.getStuId() + "|" + x.getName()).collect(Collectors.joining("\n", "+++", "---"));
System.out.println(s);
}
2.Optional容器类
(1)一个容器类,代表一个值存在或者不存在(null),为了避免控制异常,用起来十分方便。
@Test
public void test1() {
//创建一个Optional实例
Optional<Student> op1 = Optional.of(new Student("2"));
System.out.println(op1);
// Optional.of(null); NullPointerException
//创建一个空对象
Optional<Student> op2 = Optional.empty();
System.out.println(op2);
//有值则创建一个Optional实例,无创建一个空对象
Optional<String> op3 = Optional.ofNullable(null);
System.out.println(op3);
//optional 提供了一个方法 isPresent判断是否有值
if(op3.isPresent()){
System.out.println(op3);
}
}
输出结果:
Optional[Student(stuId=null, name=2, age=null, matchScore=null)]
Optional.empty
Optional.empty
(2)实践应用
常常会遇到如果为null的时候给一个默认值
@Test
public void test2() {
//项目中经常会用到 有则干嘛, 无责干嘛 if else
Optional<String> op1 = Optional.ofNullable(new String("1"));
Student st = new Student("test");
String op = Optional.ofNullable(st.getName()).orElse("@");
System.out.println(op);
Optional<Student> op2 = Optional.ofNullable(new Student("mayun"));
Optional<Student> op3 = Optional.empty();
Student s1 = op2.orElseGet(() -> new Student("mahuateng"));
Student s2 = op3.orElseGet(() -> new Student("mahuateng"));
System.out.println(s1 + "++++" + s2);
}
输出结果:
test
Student(stuId=null, name=mayun, age=null, matchScore=null)++++Student(stuId=null, name=mahuateng, age=null, matchScore=null)
欢迎大家一起来补充修正!!!
网友评论