Java流操作——Stream(一)


文章目录

  • Java流操作——Stream(一)
  • 前言
  • 一、流是什么?
  • 二、流的使用
  • 1.流的创建
  • 2.filter、map、distinct、sorted和peek的使用
  • 3.抽取子流和连接流limit,skip,concat
  • 4.约简操作count,min,max,findFirst,findAny,anyMatch,allMatch,noneMatch



前言

流是一种用来以“做什么而非怎么做”的方式处理集合。

一、流是什么?

平常在处理集合时我们会迭代遍历集合,例如我们统计长度大于3的字符串时会用以下for循环去一个一个遍历然后判断条件。

public static void main(String[] args){
        List<String> words= Arrays.asList("ABC","ewqwrqr","fsfasfa","faeqrqtq");
        int count=0;
        for (String word : words) {
            if(word.length()>3){
                count++;
            }
        }
        System.out.println(count);
    }

在使用流操作时 我们只需要先调用stream方法产生一个流,然后filter方法会返回过滤后的一个新流,count方法会将流简化为一个结果返回。

public static void main(String[] args){
        List<String> words= Arrays.asList("ABC","ewqwrqr","fsfasfa","faeqrqtq");
        long count=words.stream().filter(x->x.length()>3).count();
        System.out.println(count);
    }

对比以上方法,我们可以发现流的操作比普通的循环遍历更简洁明了,每一步都可以通过方法名看出每一步操作的意义。在以上流示例中我们只需要指明每一步需要做什么,而至于怎么循环,在哪个线程去操作完成我们不需要关心。

二、流的使用

1.流的创建

//通过给定元素创建流
        Stream<String> stream= Stream.of("ABC","ewqwrqr","fsfasfa","faeqrqtq");
        //创建一个不包含任何元素的流
        Stream<String> stream1= Stream.empty();
        //创建一个无限流反复调用函数s构成
        Stream<Integer> stream2= Stream.generate(()->0);
        //创建一个无限流通过函数x在种子数据上操作生成
        Stream<BigInteger> stream3= Stream.iterate(BigInteger.ZERO,x->x.add(BigInteger.ONE));
        //创建一个流通过指定文件的行
        Stream<String> stream4= Files.lines(Paths.get(""), StandardCharsets.UTF_8);

2.filter、map、distinct、sorted和peek的使用

  • filter、map流
List<String> words= Arrays.asList("ABC","ewqwrqr","fsfasfa","faeqrqtq");
        //返回一个与某种条件匹配后的新流,filter的引元时Predicate<T>,即从T到boolean的函数
        Stream<String> stream1= words.stream().filter(x->x.length()>3);
        //通过某种方式转换流中的值,使用map时会有一个函数应用在每个值上
        Stream<String> stream2= words.stream().map(String::toLowerCase);
        Stream<String> stream3= words.stream().map(s->s.substring(0,1));
  • distinct流,过滤重复元素,通过equals()方法判断两元素是否相同
//剔除相同元素,打印出ABCD
        List<String> contact= Arrays.asList("A","B","C","D","D","C");
        Stream<String> stream = contact.stream().distinct();
  • sorted排序
//sorted排序,按照字符串长度排序
        List<String> contact= Arrays.asList("Dream","Busy","Cat","Dog");
        Stream<String> stream = contact.stream().sorted(Comparator.comparing(String::length));
  • peek会产生一个新流,它的元素与原来流中元素相同,但是在每次获取一个元素的时候,都会调用一个函数
//产生一个与原来流中国元素相同的新流,同时打印每个元素的长度
        List<String> contact= Arrays.asList("Dream","Busy","Cat","Dog");
        Stream<String> stream = contact.stream().peek(e-> System.out.println(e.length()));

3.抽取子流和连接流limit,skip,concat

  • stream.limit(n)会返回当前流中前n个元素的新流
//产生一个包含100个随机数的流
       Stream<Double> randoms=Stream.generate(Math::random).limit(100);
  • stream.skip(n)正好相反,他会丢弃前n个元素
//跳过第一个元素,打印出BCD
        List<String> contact= Arrays.asList("A","B","C","D");
        Stream<String> random=contact.stream().skip(1);
  • stream的concat方法将两个流连接起来
//拼接两个流,打印出ABCD
        List<String> contact= Arrays.asList("A","B");
        List<String> contact2= Arrays.asList("C","D");
        Stream<String> stream = Stream.concat(contact.stream(), contact2.stream());

4.约简操作count,min,max,findFirst,findAny,anyMatch,allMatch,noneMatch

约简操作是一种终结操作,他会将流约简为在程序中可以使用的非流值。如count,min,max,findFirst,findAny,anyMatch,allMatch,noneMatch

Stream<String> contact= Stream.of("Dream","Busy","Cat","Dog");
        //返回流中元素个数
        long count =contact.count();
        //返回流中最大值
        Optional<String> max = contact.max(String::compareToIgnoreCase);
        //返回流中最小值
        Optional<String> min = contact.min(String::compareToIgnoreCase);
        //找到第一个D开头的字符串
        Optional<String> optional = contact.filter(x -> x.startsWith("Q")).findFirst();
        //判断是否存在以D开头的字符串
        boolean q = contact.anyMatch(x -> x.startsWith("Q"));
        //判断是否所有字符串都以D开头的字符串
        boolean b = contact.allMatch(x -> x.startsWith("Q"));
        //判断是否所有字符串都不以D开头的字符串
        boolean p = contact.noneMatch(x -> x.startsWith("Q"));