List的Stream流操作

面对一对多结构,查询主实体时需要附带主实体的子实体列表怎么写?查出主列表,循环查子列表

List的Stream流操作可以简化我们的代码,减少程序运行的压力,应对上面的问题,以前的话是先查出对应的list数据,然后根据取到集合中id去查找对应的子实体中数据,接着在放入对应的集合中去,key值表示主实体的id,value值表示对应主实体id查到的对象数据,这样会很麻烦,当数据量大的时候,会增加程序运行的负荷,造成运行缓慢。所以,流式操作代替我们的这一堆操作,提高了代码的简易性,可维护性,可靠性,更不容易出错。
举例一些流式操作的例子:

// An highlighted block
class Person{
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
 public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Person person = (Person) o;
    return age == person.age &&
            Objects.equals(name, person.name);
}

@Override
public int hashCode() {
    return Objects.hash(name, age);
}


List<Person> list = new ArrayList<>();
list.add(new Person("jack", 20));
list.add(new Person("mike", 25));
list.add(new Person("tom", 30));

1.stream() / parallelStream()
最常用到的方法,将集合转换为流

List list = new ArrayList();
// return Stream<E>
list.stream();

parallelStream() 是并行流方法,能够让数据集执行并行操作

2.filter(T -> boolean)
保留 boolean 为 true 的元素

保留年龄为 20 的 person 元素

list = list.stream()
            .filter(person -> person.getAge() == 20)
            .collect(toList());

//打印输出 [Person{name='jack', age=20}]

collect(toList()) 可以把流转换为 List 类型

3.distinct()

去除重复元素,这个方法是通过类的 equals 方法来判断两个元素是否相等的
如例子中的 Person 类,需要先定义好 equals 方法,不然类似[Person{name=‘jack’, age=20}, Person{name=‘jack’, age=20}] 这样的情况是不会处理的

List<Person> list = new ArrayList<>();
list.add(new Person("jack", 20));
list.add(new Person("mike", 25));
list.add(new Person("tom", 30));
list.add(new Person("jack", 20));
list = list.stream()
        .distinct()
        .collect(toList());
System.out.println(Arrays.toString(list.toArray()));
//输出  [Person{name='jack', age=20}, Person{name='mike', age=25}, Person{name='tom', age=30}]

4.sorted() / sorted((T, T) -> int)

如果流中的元素的类实现了 Comparable 接口,即有自己的排序规则,那么可以直接调用 sorted() 方法对元素进行排序,如 Stream
反之, 需要调用 sorted((T, T) -> int) 实现 Comparator 接口
根据年龄大小来比较:

list = list.stream()
           .sorted((p1, p2) -> p1.getAge() - p2.getAge())
           .collect(toList());
System.out.println(Arrays.toString(list.toArray()));
//输出   [Person{name='jack', age=20}, Person{name='mike', age=25}, Person{name='tom', age=30}]

这个可以简化为

list = list.stream()
          .sorted(Comparator.comparingInt(Person::getAge))
          .collect(toList());

5.limit(long n)
返回前 n 个元素

list = list.stream()
            .limit(2)
            .collect(toList());

//打印输出 [Person{name='jack', age=20}, Person{name='mike', age=25}]

6.skip(long n)
去除前 n 个元素

list = list.stream()
            .skip(2)
            .collect(toList());

//打印输出 [Person{name='tom', age=30}]

skip(m)用在 limit(n) 前面时,先去除前 m 个元素再返回剩余元素的前 n 个元素
limit(n) 用在 skip(m) 前面时,先返回前 n 个元素再在剩余的 n 个元素中去除 m 个元素


list = list.stream()
            .limit(2)
            .skip(1)
            .collect(toList());

//打印输出 [Person{name='mike', age=25}]

7.map(T -> R)
将流中的每一个元素 T 映射为 R(类似类型转换)

List<String> newlist = list.stream().map(Person::getName).collect(toList());

newlist 里面的元素为 list 中每一个 Person 对象的 name 变量

8.flatMap(T -> Stream)
将流中的每一个元素 T 映射为一个流,再把每一个流连接成为一个流

List<String> list = new ArrayList<>();
list.add("aaa bbb ccc");
list.add("ddd eee fff");
list.add("ggg hhh iii");
list = list.stream().map(s -> s.split(" ")).flatMap(Arrays::stream).collect(toList());
//打印输出  [aaa, bbb, ccc, ddd, eee, fff, ggg, hhh, iii]

上面例子中,我们的目的是把 List 中每个字符串元素以" "分割开,变成一个新的 List。
首先 map 方法分割每个字符串元素,但此时流的类型为 Stream<String[ ]>,因为 split 方法返回的是 String[ ] 类型;所以我们需要使用 flatMap 方法,先使用Arrays::stream将每个 String[ ] 元素变成一个 Stream 流,然后 flatMap 会将每一个流连接成为一个流,最终返回我们需要的 Stream
9.anyMatch(T -> boolean)
流中是否有一个元素匹配给定的 T -> boolean 条件
是否存在一个 person 对象的 age 等于 20:

boolean b = list.stream().anyMatch(person -> person.getAge() == 20);

10.allMatch(T -> boolean)
流中是否所有元素都匹配给定的 T -> boolean 条件

11.noneMatch(T -> boolean)
流中是否没有元素匹配给定的 T -> boolean 条件

12.findAny() 和 findFirst()
findAny():找到其中一个元素 (使用 stream() 时找到的是第一个元素;使用 parallelStream() 并行时找到的是其中一个元素)
findFirst():找到第一个元素

值得注意的是,这两个方法返回的是一个 Optional 对象,它是一个容器类,能代表一个值存在或不存在

13.reduce((T, T) -> T) 和 reduce(T, (T, T) -> T)
用于组合流中的元素,如求和,求积,求最大值等
计算年龄总和:

int sum = list.stream().map(Person::getAge).reduce(0, (a, b) -> a + b);

与之相同:

int sum = list.stream().map(Person::getAge).reduce(0, Integer::sum);

其中,reduce 第一个参数 0 代表起始值为 0,lambda (a, b) -> a + b 即将两值相加产生一个新值
同样地:
计算年龄总乘积:

int sum = list.stream().map(Person::getAge).reduce(1, (a, b) -> a * b);

当然也可以

Optional<Integer> sum = list.stream().map(Person::getAge).reduce(Integer::sum);

即不接受任何起始值,但因为没有初始值,需要考虑结果可能不存在的情况,因此返回的是 Optional 类型

14.count()
返回流中元素个数,结果为 long 类型

15.collect()
收集方法,我们很常用的是 collect(toList()),当然还有 collect(toSet()) 等,参数是一个收集器接口

16.forEach()
返回结果为 void,很明显我们可以通过它来干什么了,比方说:

打印各个元素:

list.stream().forEach(System.out::println);

17. unordered()
还有这个比较不起眼的方法,返回一个等效的无序流,当然如果流本身就是无序的话,那可能就会直接返回其本身

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值