使用 Java 8 Stream 优雅的找出重复数据
最近经常遇到问题:要获取到集合中某一属性值重复的数据,除了for 循环,还有更简单得处理方式?
先来引入 Stream 流的概念。
Stream 阐述
Stream API(java.util.stream.*)
是 Java 8 中新增重要特性。
Stream 将要处理的元素集合看作一种流,由于java.util.stream.Stream
是一个 Interface
,在其中提供了函数方法,
使流在管道中进行一系列处理(如过滤,映射,聚合等)后生成的结果集合,类似于在数据库执行 SQL 语句。
这个过程通常不会对数据源造成影响。
1
2
3
4
5
6List<String> myList = Arrays.asList("a1", "a2", "b1", "c2", "c1");
myList.stream()
.filter(s -> s.startsWith("c"))
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println); // C1 C2
在以上示例中, 创建 Stream 流,filter,map 和 sorted 是中间操作,而 forEach 是一个终端操作。Stream操作链称为操作管道。
Stream 用法
可以从各种数据源中创建 Stream 流,其中以 Collection 集合最为常见。
如 List 和 Set 均支持 stream() 方法来创建顺序流 stream() 或者是并行流 parallelStream()。
常用创建 Stream 流方法
1.使用 Collection 下的 stream() 和 parallelStream() 方法来创建 Stream
1
2
3List<String> list = new ArrayList<>();
Stream<String> stream = list.stream(); //获取一个顺序流
Stream<String> parallelStream = list.parallelStream(); //获取一个并行流
2.Arrays 提供了创建流的静态方法 stream(),将数组转成流
1
2Integer[] nums = new Integer[10];
Stream<Integer> stream = Arrays.stream(nums);
3.使用 Stream 中的静态方法:of()、iterate()、generate()
1
2
3
4
5
6
7Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 2).limit(6);
stream2.forEach(System.out::println); // 0 2 4 6 8 10
Stream<Double> stream3 = Stream.generate(Math::random).limit(2);
stream3.forEach(System.out::println);
4.使用 Pattern.splitAsStream() 方法,将字符串分隔成流
1
2
3Pattern pattern = Pattern.compile(",");
Stream<String> stringStream = pattern.splitAsStream("a,b,c,d");
stringStream.forEach(System.out::println);
5.一些类也提供了创建流的方法:
1
2
3IntStream.range(start, stop);
BufferedReader.lines();
Random.ints();
中间操作 Stream 流
1.filter:用于通过设置的条件过滤出元素,其中java.util.Objects
提供了空元素的过滤
2.映射 map 方法用于映射每个元素到对应的结果
3.排序 sorted:使用 java.util.Comparator
或者 reversed
更方便的对流进行升降排序
4.distinct:通过流中元素的 hashCode() 和 equals() 去除重复元素
5.skip(n):跳过n元素,配合limit(n)可实现分页
6.limit(n):用于获取指定数量的流…
终端操作 Stream 流
1.forEach() 迭代流中的每个元素,java.util.function.Consumer
接受参数没有返回值
1
Stream.of(1,2,3,4,5).forEach(System.out::println);
2.collect() 可用于返回列表或字符串,java.util.Collectors
类中有求和、计算均值、取最值、字符串连接等多种收集方法。
1
2
3List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl");
List<String> count = strings.stream().filter(string -> string.isEmpty()).collect(Collectors.toList());
System.out.println(count.size()); // 2
3.reduce 用于对stream中元素进行聚合求值,操作函数 accumulator 接受两个参数x,y返回r
4.anyMatch()、allMatch()、noneMatch() 接收参数Predicate,返回boolean。
5.findFirst()、findAny()、count()、max()、min() …
使用 Stream 流解决集合中数据重复问题
我们以 Employee 为实体,对比 获取重复code值的 写法:
Employee 实体:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18public class Employee extends Model<Employee> {
@ApiModelProperty(value = "ID")
@TableField("ID")
private Long id;
@ApiModelProperty(value = "编码")
@TableId("CODE")
private String code;
@ApiModelProperty(value = "姓名")
@TableField("NAME")
private String name;
@ApiModelProperty(value = "年龄")
@TableField("AGE")
private Integer age;
...
}
for 写法:
1 | List<String> duplicate_code = new ArrayList<>(); |
Stream 写法:
1 | List<String> duplicate_code = new ArrayList<>(); |
由此可见,使用Java 8 的 Stream 流方式获取到集合中某一属性值重复数据的问题更方便、简洁!
了解更多有关 Java8 Stream 流的相关信息,请参考 Stream Javadoc 阅读官方文档。
Title: 使用 Java 8 Stream 优雅的找出重复数据
Author: Amber
Date: 2021-11-30
Last Update: 2024-10-29
Blog Link: https://wyiyi.github.io/amber/2021/11/30/stream/
Copyright Declaration: Copyright © 2022 Amber.