JAVA-流式计算(1.8)

流(Stream) 是什么?

是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。
“集合讲的是数据,流讲的是计算!”
特点
1)、Stream 自己不会存储元素
2)、Stream 不会改变源对象。相反, 他们会返回一个持有结果的新Stream。
3)、Stream 操作是延迟执行的。这意味着 他们会等到需要结果的时候才执行。
使用
创建一个Stream:一个数据源(数组、集合)

中间操作:一个中间操作,处理数据源数据

终止操作:一个终止操作,执行中间操作链,产生结果

public class TestStream {
    public static void main(String[] args) {
        User u1 = new User(1, "name1", 18);
        User u2 = new User(2, "name2", 20);
        User u3 = new User(3, "name3", 22);
        User u4 = new User(4, "name4", 23);
        User u5 = new User(5, "name5", 25);
        User u6 = new User(6, "name6", 26);
        //数据源
        List<User> list = Arrays.asList(u1, u2, u3, u4, u5, u6);
        //filter过滤,找出id为偶数的数据
        list.stream().filter((t) -> {
            return t.getId() % 2 == 0;
        }).filter(t -> {
            return t.getAge() >= 22;
            //map操作数据 
        }).map(m -> {
            return m.getName().toUpperCase();
            //sort进行排序
        }).sorted((o1, o2) -> {
            return o2.length() - o1.length();
            //limit现在数据条数
        }).limit(1)
                //进行foreach输出
                .forEach((b) -> {
                    System.out.println(b);
                });
    }
}

常用的方法
1、Stream filter(Predicate<? super T> predicate):过滤,返回一个boolean值

我们希望过滤赛选处所有学校是清华大学的user:

System.out.println("学校是清华大学的user");
List<User> userList1 = list.stream()
    .filter(user -> "清华大学".equals(user.getSchool()))
    .collect(Collectors.toList());
userList1.forEach(user -> System.out.print(user.name + '、'));

2、Stream distinct(); 去重

3、Stream limit(long maxSize); 传入输出的个数

如获取年龄是偶数的前2名user:

System.out.println("年龄是偶数的前两位user");
List<User> userList3 = list.stream()
    .filter(user -> user.getAge() % 2 == 0)
    .limit(2)
    .collect(Collectors.toList());
userList3.forEach(user -> System.out.print(user.name + '、'));

4、Stream sorted(Comparator<? super T> comparator); 排序,可自定义排序

如现在我想将所有user按照age从大到小排序:

System.out.println("按年龄从大到小排序");
List<User> userList4 = list.stream()
    .sorted((s1,s2) -> s2.age - s1.age)
    .collect(Collectors.toList());
userList4.forEach(user -> System.out.print(user.name + '、'));

5、Stream skip(long n); 跳过n个输出

如输出list集合跳过前两个元素后的list

System.out.println("跳过前面两个user的其他所有user");
List<User> userList5 = list.stream().
    skip(2).
    collect(Collectors.toList());
userList5.forEach(user -> System.out.print(user.name + '、'));

6、 Stream map(Function<? super T, ? extends R> mapper);:获取某个字段的集合

如获取学校是清华大学的所有学生的名字

System.out.println("学校是清华大学的user的名字");
List<String> userList6 = list.stream()
    .filter(user -> "清华大学".equals(user.school))
    .map(User::getName)
    .collect(Collectors.toList());
userList6.forEach(user -> System.out.print(user + '、')); 

7、 Stream flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

一个流中的每个值都转成一个个流,然后再将这些流扁平化成为一个流

String[] strings = {"Hello", "World"};
List l11 = Arrays.stream(strings)
    .map(str -> str.split(""))
    .map(str2->Arrays.stream(str2))
    .distinct().collect(Collectors.toList());
List l2 = Arrays.asList(strings)
    .stream()
    .map(s -> s.split(""))
    .flatMap(Arrays::stream)
    .distinct().collect(Collectors.toList());
System.out.println(l11.toString());
System.out.println(l2.toString());  

输出结果如下:
[java.util.stream.ReferencePipeline$Head@4c203ea1, java.util.stream.ReferencePipeline$Head@27f674d]
[H, e, l, o, W, r, d]  

8、boolean allMatch(Predicate<? super T> predicate);

用于检测是否全部都满足指定的参数行为,如果全部满足则返回true

System.out.println("判断是否所有user的年龄都大于9岁");
Boolean b = list.stream().
    allMatch(user -> user.age >9);
System.out.println(b);

9、boolean anyMatch(Predicate<? super T> predicate);

anyMatch则是检测是否存在一个或多个满足指定的参数行为,如果满足则返回true

System.out.println("判断是否有user的年龄是大于15岁");
Boolean bo = list.stream().anyMatch(user -> user.age >15);
System.out.println(bo);

10、boolean noneMatch(Predicate<? super T> predicate);

用于检测是否不存在满足指定行为的元素

System.out.println("判断是否不存在年龄是15岁的user");
Boolean boo = list.stream().
    noneMatch(user -> user.age == 15);
System.out.println(boo);

11、Optional findFirst();

findFirst用于返回满足条件的第一个元素,

System.out.println("返回年龄大于12岁的user中的第一个");
Optional<User> first = list.stream()
    .filter(u -> u.age > 10)
    .findFirst();
User user = first.get();
System.out.println(user.toString());

12、Optional findAny();

findAny相对于findFirst的区别在于,findAny不一定返回第一个,而是返回任意一个

System.out.println("返回年龄大于12岁的user中的任意一个");
Optional<User> anyOne = list.stream()
    .filter(u -> u.age > 10)
    .findAny();
User user2 = anyOne.get();
System.out.println(user2.toString());

收集
前面利用collect(Collectors.toList())是一个简单的收集操作,是对处理结果的封装,对应的还有toSet、toMap,以满足我们对于结果组织的需求。这些方法均来自于java.util.stream.Collectors,我们可以称之为收集器。
收集器也提供了相应的归约操作,但是与reduce在内部实现上是有区别的,收集器更加适用于可变容器上的归约操作,这些收集器广义上均基于Collectors.reducing()实现。

1 counting
计算个数

如我现在计算user的总人数,实现如下:

System.out.println("user的总人数");
long COUNT = list.stream().count();//简化版本
long COUNT2 = list.stream()
    .collect(Collectors.counting());//原始版本
System.out.println(COUNT);
System.out.println(COUNT2);

2 maxBy、minBy
maxBy(Comparator<? super T> comparator)
minBy(Comparator<? super T> comparator)
计算最大值和最小值

如我现在计算user的年龄最大值和最小值:

System.out.println("user的年龄最大值和最小值");
Integer maxAge =list.stream()
    .collect(
        Collectors.maxBy((s1, s2) -> s1.getAge() - s2.getAge()))
     .get().age;
Integer maxAge2 = list.stream().collect(
        Collectors.maxBy(Comparator.comparing(User::getAge)))
      .get().age;
Integer minAge = list.stream().collect(
        Collectors.minBy((S1,S2) -> S1.getAge()- S2.getAge()))
      .get().age;
Integer minAge2 = list.stream().collect(
        Collectors.minBy(Comparator.comparing(User::getAge)))
      .get().age;
System.out.println("maxAge = " + maxAge);
System.out.println("maxAge2 = " + maxAge2);
System.out.println("minAge = " + minAge);
System.out.println("minAge2 = " + minAge2);

3 summingInt、summingLong、summingDouble
ummingInt(ToIntFunction<? super T> mapper)
总和

如计算user的年龄总和:

System.out.println("user的年龄总和");
Integer sumAge =list.stream().collect(Collectors.summingInt(User::getAge));
System.out.println("sumAge = " + sumAge)

4 averageInt、averageLong、averageDouble
averagingInt(ToIntFunction<? super T> mapper)
平均值

如计算user的年龄平均值:

System.out.println("user的年龄平均值");
double averageAge = list.stream().collect(Collectors.averagingDouble(User::getAge));
System.out.println("averageAge = " + averageAge);

5 summarizingInt、summarizingLong、summarizingDouble
一次性查询元素个数、总和、最大值、最小值和平均值

System.out.println("一次性得到元素个数、总和、均值、最大值、最小值");
long l1 = System.currentTimeMillis();
IntSummaryStatistics summaryStatistics = list.stream().collect(Collectors.summarizingInt(User::getAge));
long l111 = System.currentTimeMillis();
System.out.println("计算这5个值消耗时间为" + (l111-l1));
System.out.println("summaryStatistics = " + summaryStatistics);


输出结果为:
一次性得到元素个数、总和、均值、最大值、最小值
计算这5个值消耗时间为3
summaryStatistics = IntSummaryStatistics{count=10, sum=145, min=10, average=14.500000, max=25}

6 joining
Collector<CharSequence, ?, String> joining(CharSequence delimiter)
字符串拼接

如输出所有user的名字,用“,”隔开

System.out.println("字符串拼接");
String names = list.stream()
    .map(User::getName).collect(Collectors.joining(","));
System.out.println("names = " + names);

输出结果为:
字符串拼接
names = 张三,李四,王五,赵六,田七,小明,小红,小华,小丽,小何

7 groupingBy
分组
Collector<T, ?, Map<K, List>> groupingBy(Function<? super T, ? extends K> classifier)

如将user根据学校分组、先按学校分再按年龄分、每个大学的user人数、每个大学不同年龄的人数:

System.out.println("分组");
Map<String, List<User>> collect1 = list.stream()
    .collect(Collectors.groupingBy(User::getSchool));
Map<String, Map<Integer, Long>> collect2 = list.stream()
    .collect(Collectors.groupingBy(User::getSchool, Collectors.groupingBy(User::getAge, Collectors.counting())));
Map<String, Map<Integer, Map<String, Long>>> collect4 = 
    list.stream()
    .collect(Collectors.groupingBy(User::getSchool, Collectors.groupingBy(User::getAge, Collectors.groupingBy(User::getName,Collectors.counting()))));
Map<String, Long> collect3 = list.stream()
    .collect(Collectors.groupingBy(User::getSchool, Collectors.counting()));
System.out.println("collect1 = " + collect1);
System.out.println("collect2 = " + collect2);
System.out.println("collect3 = " + collect3);
System.out.println("collect4 = " + collect4);

输出结果为:
分组
collect1 = {浙江大学=[User{id=8, name='小华', age=14, school='浙江大学'}, User{id=9, name='小丽', age=17, school='浙江大学'}, User{id=10, name='小何', age=10, school='浙江大学'}], 北京大学=[User{id=5, name='田七', age=25, school='北京大学'}, User{id=6, name='小明', age=16, school='北京大学'}, User{id=7, name='小红', age=14, school='北京大学'}], 清华大学=[User{id=1, name='张三', age=10, school='清华大学'}, User{id=2, name='李四', age=12, school='清华大学'}, User{id=3, name='王五', age=15, school='清华大学'}, User{id=4, name='赵六', age=12, school='清华大学'}]}
collect2 = {浙江大学={17=1, 10=1, 14=1}, 北京大学={16=1, 25=1, 14=1}, 清华大学={10=1, 12=2, 15=1}}
collect3 = {浙江大学=3, 北京大学=3, 清华大学=4}
collect4 = {浙江大学={17={小丽=1}, 10={小何=1}, 14={小华=1}}, 北京大学={16={小明=1}, 25={田七=1}, 14={小红=1}}, 清华大学={10={张三=1}, 12={李四=1, 赵六=1}, 15={王五=1}}}

8 partitioningBy

分区,分区可以看做是分组的一种特殊情况,在分区中key只有两种情况:true或false,目的是将待分区集合按照条件一分为二,java8的流式处理利用ollectors.partitioningBy()方法实现分区。

如按照是否是清华大学的user将左右user分为两个部分:

System.out.println("分区");
Map<Boolean, List<User>> collect5 = list.stream().collect(Collectors.partitioningBy(user1 -> "清华大学".equals(user1.school)));
System.out.println("collect5 = " + collect5);

输出结果为:
分区
collect5 = {
    false=[User{id=5, name='田七', age=25, school='北京大学'}, User{id=6, name='小明', age=16, school='北京大学'}, User{id=7, name='小红', age=14, school='北京大学'}, User{id=8, name='小华', age=14, school='浙江大学'}, User{id=9, name='小丽', age=17, school='浙江大学'}, User{id=10, name='小何', age=10, school='浙江大学'}], 
    true=[User{id=1, name='张三', age=10, school='清华大学'}, User{id=2, name='李四', age=12, school='清华大学'}, User{id=3, name='王五', age=15, school='清华大学'}, User{id=4, name='赵六', age=12, school='清华大学'}]
    }

题外话

小潘的个人微信公众号【小潘学程序】,有兴趣可给个关注~

一起学习,一起成长

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值