Java函数式编程(四)Stream的常见方法和操作

这个篇幅介绍的就是Stream常见的方法和操作,之前关于stream操作,我一般直接搜写法,然后按样子改写。主要的原因不是很了解这种链式编程,每个方法间的是使用和他们之间的顺序。但其实,看下来Stream常见的方法其实不是很多,也不是很难理解,整理清楚后,以后写起stream来底气就足了。

(1)map
map这个类似于把一个stream转换成另一个stream,比如说我有一个Student关于学生信息的实体bean,大概如下:

Class Student{
private int studentCode;
private String name;
private int sex;
}

我有一个ListsutdentList,实际上我想要的是里面的学生编码code,就可以通过转换为Student的Stream在转换为code的Stream

List<String> codeList = studentList.stream().map(Student::getStudentCode).collect(Collectors.toList())

我比较喜欢有的资料画的map方法示意图,map操作是全员,每一个都参与操作,类似下图获取平方数
在这里插入图片描述
(2)filter
实际上filter,看名字就知道是过滤的意思,和map的不同就是,map假设是10个成员参与,转换后也是10个成员,而filter是要过滤的,可能过滤完10个就剩下1个了。

示意图看起来更清楚简洁一些,对比上边的map
在这里插入图片描述
以下是关于filter的demo

public class StreamTestFilter {

    public void testFilter(){

        StreamTestFilter streamTestFilter = new StreamTestFilter();
        Stream<BigInteger> naturals = createNaturalStream();

    }

    private Stream<BigInteger> createNaturalStream(){
        Stream<BigInteger> naturals = Stream.of();
        return naturals;
    }

    @Test
    public void testFilterStudent(){
      //过滤成绩合格的学生
        List<Person> list = Arrays.asList(new Person("张三",44),new Person("李四",76),
             new Person("赵四",8),new Person("王二麻子",90));

        list.stream().filter(person -> person.score >=60 ).forEach( person -> System.out.println(person.name));

    }

    @Test
    public void testFilterForeach(){
        IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9)
                .filter(n -> n % 2 != 0)
                .forEach(System.out::println);
    }

}




class Person {
    String name;
    int score;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
}

(3)reduce
reduce这个方法之前用的比较少,但是了解到这个方法后,觉得会用这个以后代码能省略不少。reduce叫做聚合方法,我们之前曾听过一个技术大数据处理的叫做reduceMap,reduce听名字意思一般和处理聚合数据有关。

和map,filter方法不同,前两者是将一个stream转换成另一个stream(不管你是全员匹配,还是部分过滤)。reduce会得到一个结果,这个结果是stream的元素聚合而成的。

例子

public class StreamReduceDemo {

    @Test
    public  void reduceTest() {
        int sum = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).reduce(0, (acc, n) -> acc + n);
        System.out.println(sum); // 45
    }

}

看起来是不是不是很好懂,我换一种写法给你

    @Test
    public void reduceExplain(){

        List<Integer> list = Arrays.asList( 1, 2, 3, 4, 5, 6, 7, 8, 9 );
        int sum = 0;
        for (Integer n : list) {
            sum = sum + n;
        }
        System.out.println(sum);

    }

(4)转换为集合
实际上除了聚合reduce外,map和filter的转换都是stream到stream,我们也讨论过stream不同于我们的集合,虽然我们可以把集合转换为stream,但是要知道一点就是,stream更多的是是记录一种规则并不是什么数据结构,就是集合转换过来的stream也可以认为是一种规则(就是只有这几个元素的规则)。

但实际上我们敲代码要展示或者存储到数据库,不能直接用stream,所以我们要把stream输出为集合。

输出为List

@Test
    public void outList(){
        Stream<String> stream = Stream.of("Apple", "", null, "Pear", "  ", "Orange");
        List<String> list = stream.filter(s -> s != null && !s.isEmpty()).collect(Collectors.toList());
        System.out.println(list);
    }

输出为Map
Collectors.toMap()里面做key和value的处理

 @Test
    public void outMap(){
        Stream<String> stream = Stream.of("APPL:Apple", "MSFT:Microsoft");
        Map<String, String> map = stream
                .collect(Collectors.toMap(
                        // 把元素s映射为key:
                        s -> s.substring(0, s.indexOf(':')),
                        // 把元素s映射为value:
                        s -> s.substring(s.indexOf(':') + 1)));
        System.out.println(map);
    }

分组输出
我们写SQL的时候会用到group by这个分组来查询某一类的,实际上stream输出也有类似的分组的功能,当然两者不能混淆,实际上这个分组有时候类似我们SQL里面的order by(要知道group by的用法和order by也是很大的)

 @Test
    public void outGroup(){
        String[] arrays = {"Apple", "Banana", "Blackberry", "Coconut", "Avocado", "Cherry", "Apricots"};
        List<String> list =  Arrays.asList(arrays);
        System.out.println(list);
        Map<String, List<String>> groups = list.stream()
                .collect(Collectors.groupingBy(s -> s.substring(0, 1), Collectors.toList()));
        System.out.println(groups);
    }

最后一个完整的demo,里面最后一个是关于多个词分组的

public class StreamOutTest {

    @Test
    public void outList(){
        Stream<String> stream = Stream.of("Apple", "", null, "Pear", "  ", "Orange");
        List<String> list = stream.filter(s -> s != null && !s.isEmpty()).collect(Collectors.toList());
        System.out.println(list);
    }

    @Test
    public void outMap(){
        Stream<String> stream = Stream.of("APPL:Apple", "MSFT:Microsoft");
        Map<String, String> map = stream
                .collect(Collectors.toMap(
                        // 把元素s映射为key:
                        s -> s.substring(0, s.indexOf(':')),
                        // 把元素s映射为value:
                        s -> s.substring(s.indexOf(':') + 1)));
        System.out.println(map);
    }

    @Test
    public void outGroup(){
        String[] arrays = {"Apple", "Banana", "Blackberry", "Coconut", "Avocado", "Cherry", "Apricots"};
        List<String> list =  Arrays.asList(arrays);
        System.out.println(list);
        Map<String, List<String>> groups = list.stream()
                .collect(Collectors.groupingBy(s -> s.substring(0, 1), Collectors.toList()));
        System.out.println(groups);
    }

  @Test
  public void outGroupStudent(){
      Stream<Student> studentStream = Stream.of(
              new Student(2, 3, "小明", 80),
              new Student(3, 1, "小王", 90),
              new Student(1, 2, "小强", 100),
              new Student(3, 1, "小红", 90),
              new Student(1, 2, "小黄", 100),
              new Student(2, 3, "小黑", 80),
              new Student(1, 2, "小军", 100),
              new Student(2, 3, "小乔", 80),
              new Student(3, 1, "小林", 90));
      Map<Integer, Map<Integer, List<Student>>> studentByGradeAndClass
              = studentStream.collect(
              Collectors.groupingBy(Student::getGradeId,
                      Collectors.groupingBy(Student::getClassId)));
      studentByGradeAndClass.forEach((k, m) -> {
          System.out.print("Grade" + k + " ");
          m.forEach((key, value) -> System.out.println("Class" + key + " = " + value));
          m.forEach((key,value) -> value.forEach(student -> System.out.println(student.getName()) ) );
      });
  }

}

class Student{
    int gradeId; // 年级
    int classId; // 班级
    String name; // 名字
    int score; // 分数

    Student( int gradeId,int classId,String name,int score ){
        this.gradeId = gradeId;
        this.classId = classId;
        this.name = name;
        this.score = score;
    }

    public int getGradeId() {
        return gradeId;
    }

    public void setGradeId(int gradeId) {
        this.gradeId = gradeId;
    }

    public int getClassId() {
        return classId;
    }

    public void setClassId(int classId) {
        this.classId = classId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
}

(5) 其他操作
排序
sorted()

去重
distinct()

截取
skip()和limit()的配合使用,skip是跳过,limit是限制

List.of("A", "B", "C", "D", "E", "F")
    .stream()
    .skip(2) // 跳过A, B
    .limit(3) // 截取C, D, E
    .collect(Collectors.toList()); // [C, D, E]

合并
contact(),SQL也有类似的语句方法

Stream<String> s1 = List.of("A", "B", "C").stream();
Stream<String> s2 = List.of("D", "E").stream();
// 合并:
Stream<String> s = Stream.concat(s1, s2);
System.out.println(s.collect(Collectors.toList())); // [A, B, C, D, E]

合并集合
比如几个相同的集合可以合并在一起

Stream<List<Integer>> s = Stream.of(
        Arrays.asList(1, 2, 3),
        Arrays.asList(4, 5, 6),
        Arrays.asList(7, 8, 9));

Stream<Integer> i = s.flatMap(list -> list.stream());

在这里插入图片描述
并行
parallel()

Stream<String> s = ...
String[] result = s.parallel() // 变成一个可以并行处理的Stream
                   .sorted() // 可以进行并行排序
                   .toArray(String[]::new);

Stream提供的常用操作有:

转换操作:map(),filter(),sorted(),distinct();

合并操作:concat(),flatMap();

并行处理:parallel();

聚合操作:reduce(),collect(),count(),max(),min(),sum(),average();

其他操作:allMatch(), anyMatch(), forEach()。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值