JDK8 stream处理集合的用法
本文最后更新于 1085 天前,其中的信息可能已经有所发展或是发生改变。

之前看项目代码时经常发现操作集合时用到了stream,但是看不太懂,于是决定写一篇博客作为学习笔记以便日后查验

概念

Stream是JDK8 API引入的新特性,用于对集合、数组进行复杂的查找、过滤、映射数据等操作。

工作原理:
把数据源(集合、数组等)转化成stream流并且进行一系列中间操作,最后产生一个新流。
  • 特点
1、stream自己不会存储元素
2、stream不会改变源对象
3、stream操作是惰性的,即需要结果时才执行
  • 操作步骤
(1)获取stream流
通过一个数据源获取一个流
(2)中间操作
一个中间操作链,对数据源的流进行处理
(3)终止操作
一个终止操作,执行中间操作链,并产生结果

获取stream流

  • 通过Collection系列集合提供的stream()或parallelstream()
List<String> list = new ArrayList();
Stream<string> stream1= list.stream();
//stream()获取的是串行流
//parallelstream()获取的是并行流
  • 通过Arrays中的静态方法stream()获取数组流
int[] a = new int[];
Stream<int> stream2 = Array.stream(a);
  • 通过Stream类中的静态方法of()
Stream<String> stream3 = Stream.of("aa","bb","cc");
  • 创建无限流
//迭代
Steam<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);

//生成
Stream.generate(() -> Math.random());

中间操作

多个中间操作可以连接起来形成流水线操作的返回值仍然是Stream),除非流水线上出发终止操作,否则中间操作不会执行任何处理,而在终止操作时一次性全部处理完,称为“惰性求值

筛选与切片

filter(lambda):
接受lambda函数,根据函数从流中排除某些元素

limit(num):
截断流,使其元素不超过num

skip(num):
跳过num个元素。若流中元素不足n个,则返回一个空流。
与limit互补。

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

employees集合:(pojo省略)

List<Employee> employees = Arrays.asList(
        new Employee("张三",18,9999.99),
        new Employee("李四",58,5555.55),
        new Employee("王五",26,3333.33),
        new Employee("赵六",36,6666.66),
        new Employee("田七",12,8888.88)
    )
//Array.asList():将数组转化为List

Stream:

employees.stream()
         .filter((x) -> x.getAge() > 12)
         .limit(2)
         .distinct()
         .skip(1)
         .forEach(System.out::println);

/*
结果:
李四 58 5555.55
王五 26 3333.33
*/
System.out::println是java8的一种新特性:方法引用
本质是对lambda表达式的进一步简化
这里等价于(str)->System.out.println(str)

映射

map(lambda):
接收lambda函数,该函数会被用到每个元素上,将其映射成一个新的元素。

flatMap(lambda):
接收lambda函数,将流中的每个值都转换成另一个流,再把所有的流连接成一个流

Map和flatMap的区别:flatMap是对流进行扁平化处理
(我对这个flatMap的理解是拆分+连接,Map是无拆分+连接;map()类似于List的add(),flatMap类似于List的addAll()
(初见扁“扁平化处理”这个词时感觉很怪,但是看了一些实例、了解了这两者的区别后,发现这个词用的真的太妙了)
  • map:
Arrays.asList("a","b","c").stream()
                         .map((str)->str.toUpperCase())
                         .forEach(System.out::println);

/*
结果:
A
B
C
*/
  • flatMap:
        Arrays.asList("aaa", "bbb", "ccc").stream()
                .flatMap((str) -> {
                            List<Character> list = new ArrayList<>();
                            for (char c : str.toCharArray()) {
                                list.add(c);
                            }
                            return list.stream();
                        }
                )
                .forEach(System.out::println);
/*
结果:
a
a
a
b
b
b
c
c
c
*/

排序

sorted():
自然排序
按照字典序排序

sorted(Comparator com):
定制排序
  • 示例

employees集合:(pojo省略)

 List<Employee> employees = Arrays.asList(
                new Employee("小红", 13, 5),
                new Employee("小明", 13, 7),
                new Employee("小王", 15, 3),
                new Employee("小白", 14, 7),
                new Employee("小刚", 12, 8)
        );
//Array.asList():将数组转化为List

定制排序:

 employees.stream()
                .sorted((e1, e2) -> { //compara()
                    if (e1.getAge() == (e2.getAge())) {
                        return e1.getSalary() > e2.getSalary() ? 1 : -1;
                    } else {
                        return e1.getAge() > e2.getAge() ? 1 : -1;
                    }
                })
                .forEach(System.out::println);
/*
结果:
小刚 12 8.0
小红 13 5.0
小明 13 7.0
小白 14 7.0
小王 15 3.0
*/

终止操作

查找与匹配

boolean allMatch(lambda):
检测是否匹配所有元素

boolean anyMatch(lambda):
检测是否至少匹配一个元素

boolean noneMatch(lambda):
检测是否所有元素都不匹配

Optional<T> findFirst():
返回第一个元素

Optional<T> findAny():
返回任意一个元素

long count():
返回元素个数

Optional<T> max():
返回最大值

Optional<T> min():
返回最小值

forEach(lambda)
内部迭代

规约/收集

归约:
T reduce(T identity, BinaryOperator) / 
Optional<T> reduce(BinaryOperator) 
可以将流中的数据反复结合起来,得到一个值
前者返回T,后者返回Optional<T>(表示T可能为null)

收集:
collect(collector)
将流转换成其他形式;接收一个 Collector 接口的实现,用于给流中元素做汇总的方法
Collectors实用类提供了很多静态方法用于创建收集器实例
  • 规约
//案例1:求1-10的和
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Integer sum = list.stream().reduce(0, (x, y) -> x + y);
System.out.println(sum);

//案例2:求公司员工工资总和
Optional<Double> op = employee.stream()
                .map(EMployee::getSalary)
                .reduce(Double::sum);
double sum = op.get();
System.out.println(op.get());

/*
注意:
案例1中reduce()的返回值是Integer
案例2中reduce()的返回值是Optional<T>
这是因为案例1中reduce()的返回值不可能为null,因为已经传入了一个"0"
*/
  • 收集
//案例1:获取一个包含公司所有员工名的List
List<string> list = employees.stream()
        .map(Employee::getName)
        .collect(Collectors.toList());
list.forEach(System.out::println);

/*
当需要一个特殊的集合时(比如HashSet),可以这样写:
HashSet<string> hashSet = employees.stream()
        .map(Employee::getName)
        .collect(Collectors.toCollection(HashSet::new));
hashSet.forEach(System.out::println);
*/

//案例2:返回员工年龄总数
Long count = employees.stream()
        .collect(Collection.counting());
/*
等价于
Long count = employees.stream()
        .map(Employee::getAge())
        .count();
*/

//案例3:对员工按照状态分组(分组)
Map<Status, List<Employee>> map = employees.stream()
        .collect(Collectors.groupingBy(Employee::getStatus))

//案例4:对员工先按照状态分组,后按照年龄分组(多级分组)
Map<Status, Map<String, List<Employee>>> map = employee.stream()
        .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
                return e.getAge() < 35 ? "青年" : "壮年";
        })));

//案例5:对员工工资是否达到8000进行分类(分区)
Map<Boolean, List<Employee>> map = employees.stream()
        .collect(collectors.partitioningBy((e)->e.getSalary()>8000));

//案例6:对员工的工资进行各种操作(操作)
DoubleSummaryStatistics dss = emps.stream()
        .collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(dss.getMax());
System.out.println(dss.getMin());
System.out.println(dss.getSum());
System.out.println(dss.getCount());
System.out.println(dss.getAverage());

//案例7:连接所有员工的姓名作为一个字符串(连接字符串)
String str = emps.stream()
        .map(Employee::getName)
        .collect(Collectors.joining("-")); //可传入分隔符
System.out.println(str);

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇