Java之Stream流的使用

本文介绍了Java 8的Stream API,它为处理集合和数组提供了简洁的方法。通过Stream,你可以方便地进行过滤、限制、跳过、去重、排序等操作。Stream支持中间操作和终端操作,例如filter、limit、distinct、sorted和collect。文章还展示了如何使用Stream的常用方法,如map和reduce,以及如何通过collect方法将Stream转换为各种数据结构。此外,还讨论了Stream的使用场景和为何需要流式处理,以提高数据传输效率和节省内存。最后,通过实例展示了Stream在实际编程中的应用,包括排序、分组、统计等操作。

使用好JDK8的新特性会有助于你的编程,Stream流的使用会使集合或数组的操作更加简便,更赏心悦目,相信这篇文章可以使喜欢追求细节完美的人会有所收获。

Java中什么是Stream(流)

Stream是java的1个类, 这个类专门用于程序和外部设备的输入输出(IO). 基本上所有流都在 java.io这个包中.
实际上Stream就是数据在程序和外部设备的单向管道, 流的各种方法相当于管道上的各种按钮.
所谓的外部设备可以包括硬盘文件, 网络设备, 另个程序等. 也就是当前程序之外的数据设备.

要注意在流中操作数据不能影响到原数据 把流理解成为快捷展示的过程或许好理解些(例如看电影),当然也可以通过收集方法来吧数据留存下来不过接收的集合是一个新集合和原来无关。

为什么需要Stream(流)

Stream存在的意义也很简单.

  1. 数据的传输量很大.

  2. 内存有限.

  3. 带宽有限.

而Stream可以1点1点地逐步传输所有数据, 这就是Stream存在的根本意义.

下面简单介绍一下Java中stream流的使用:

1.获取stream流  

方式a:根据Collection获取流
集合创建创建:调用集合的stream方法即可,如 list.stream()

方式b:根据Map获取流
Stream<Map.Entry<String, String>> entryStream = map.entrySet().stream();

方式c:根据静态方法获取流
Stream stream = Stream.of(new Integer[]{1,2});

注:stream流被创建出来之后只能被使用一次,如需再次循环需要再次创建!

方法d:根据Arrays工具类获取

Arrays.stream(new Integer[]{1,2})

2.常用方法介绍:

流的方法被分为中间操作和终端操作,顾名思义,中间操作是指调用方法后生成新的流,可以继续执行操作,而终端操作则是结束流的使用。

中间操作:

1.filter Stream filter(Predicate<? super T> predicate); 过滤掉不符合的数据 留下true 去除false

2.limit Stream limit(long maxSize); 只取前x条数据 

3.skip Stream skip(long n); 跳过(删除)x条数据 

4.distinct  去重复数据 (底层使用hashCode+equal)

5.sorted  排序 

6.map  Stream map(Function<? super T, ? extends R> mapper); 对数据重整,生成新的数据流(如何从用户集合流中取出用户年龄作为新的流)

终端操作:

1.count long count(); 统计数据数量

2.forEach void forEach(Consumer<? super T> action); 对流中每个数据都执行传入的方法

3.anyMatch  至少一个匹配,返回bool

4.allMatch  匹配所有,返回bool

5.collect  可以传入集合中的常用方法

static <T> Collector<T,?,Double> averagingDouble(ToDoubleFunction<? super T> mapper) 
返回一个 Collector ,它产生应用于输入元素的双值函数的算术平均值。  
static <T> Collector<T,?,Double> averagingInt(ToIntFunction<? super T> mapper) 
返回一个 Collector ,它产生应用于输入元素的整数值函数的算术平均值。  
static <T> Collector<T,?,Double> averagingLong(ToLongFunction<? super T> mapper) 
返回一个 Collector ,它产生应用于输入元素的长值函数的算术平均值。  
static <T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream, Function<R,RR> finisher) 
适应 Collector进行额外的整理转换。  
static <T> Collector<T,?,Long> counting() 
返回 Collector类型的接受元件 T计数输入元件的数量。  
static <T,K> Collector<T,?,Map<K,List<T>>> groupingBy(Function<? super T,? extends K> classifier) 
返回 Collector “由基团”上的类型的输入元件操作实现 T ,根据分类功能分组元素,并且在返回的结果 Map 。  
static <T,K,A,D> Collector<T,?,Map<K,D>> groupingBy(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream) 
返回 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。  
static <T,K,D,A,M extends Map<K,D>>
Collector<T,?,M> groupingBy(Function<? super T,? extends K> classifier, Supplier<M> mapFactory, Collector<? super T,A,D> downstream) 
返回 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。  
static <T,K> Collector<T,?,ConcurrentMap<K,List<T>>> groupingByConcurrent(Function<? super T,? extends K> classifier) 
返回一个并发 Collector “由基团”上的类型的输入元件操作实现 T ,根据分类功能分组元素。  
static <T,K,A,D> Collector<T,?,ConcurrentMap<K,D>> groupingByConcurrent(Function<? super T,? extends K> classifier, Collector<? super T,A,D> downstream) 
返回一个并发 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。  
static <T,K,A,D,M extends ConcurrentMap<K,D>>
Collector<T,?,M> groupingByConcurrent(Function<? super T,? extends K> classifier, Supplier<M> mapFactory, Collector<? super T,A,D> downstream) 
返回一个并发 Collector “由基团”上的类型的输入元件操作实现级联 T ,根据分类功能分组元素,然后使用下游的指定执行与给定键相关联的值的归约运算 Collector 。  
static Collector<CharSequence,?,String> joining() 
返回一个 Collector ,按照遇到的顺序将输入元素连接到一个 String中。  
static Collector<CharSequence,?,String> joining(CharSequence delimiter) 
返回一个 Collector ,按照遇到的顺序连接由指定的分隔符分隔的输入元素。  
static Collector<CharSequence,?,String> joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix) 
返回一个 Collector ,它将按照指定的 Collector分隔的输入元素与指定的前缀和后缀进行连接。  
static <T,U,A,R> Collector<T,?,R> mapping(Function<? super T,? extends U> mapper, Collector<? super U,A,R> downstream) 
适应一个 Collector类型的接受元件 U至类型的一个接受元件 T通过积累前应用映射函数到每个输入元素。  
static <T> Collector<T,?,Optional<T>> maxBy(Comparator<? super T> comparator) 
返回一个 Collector ,它根据给出的 Comparator产生最大元素,描述为 Optional<T> 。  
static <T> Collector<T,?,Optional<T>> minBy(Comparator<? super T> comparator) 
返回一个 Collector ,根据给出的 Comparator产生最小元素,描述为 Optional<T> 。  
static <T> Collector<T,?,Map<Boolean,List<T>>> partitioningBy(Predicate<? super T> predicate) 
返回一个 Collector ,根据Predicate对输入元素进行 Predicate ,并将它们组织成 Map<Boolean, List<T>> 。  
static <T,D,A> Collector<T,?,Map<Boolean,D>> partitioningBy(Predicate<? super T> predicate, Collector<? super T,A,D> downstream) 
返回一个 Collector ,它根据Predicate对输入元素进行 Predicate ,根据另一个 Collector减少每个分区的值,并将其组织成 Map<Boolean, D> ,其值是下游缩减的结果。  
static <T> Collector<T,?,Optional<T>> reducing(BinaryOperator<T> op) 
返回一个 Collector ,它在指定的 Collector下执行其输入元素的 BinaryOperator 。  
static <T> Collector<T,?,T> reducing(T identity, BinaryOperator<T> op) 
返回 Collector执行下一个指定的减少其输入元件的 BinaryOperator使用所提供的身份。  
static <T,U> Collector<T,?,U> reducing(U identity, Function<? super T,? extends U> mapper, BinaryOperator<U> op) 
返回一个 Collector ,它在指定的映射函数和 BinaryOperator下执行其输入元素的 BinaryOperator 。  
static <T> Collector<T,?,DoubleSummaryStatistics> summarizingDouble(ToDoubleFunction<? super T> mapper) 
返回一个 Collector , double生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。  
static <T> Collector<T,?,IntSummaryStatistics> summarizingInt(ToIntFunction<? super T> mapper) 
返回一个 Collector , int生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。  
static <T> Collector<T,?,LongSummaryStatistics> summarizingLong(ToLongFunction<? super T> mapper) 
返回一个 Collector , long生产映射函数应用于每个输入元素,并返回结果值的汇总统计信息。  
static <T> Collector<T,?,Double> summingDouble(ToDoubleFunction<? super T> mapper) 
返回一个 Collector ,它产生应用于输入元素的双值函数的和。  
static <T> Collector<T,?,Integer> summingInt(ToIntFunction<? super T> mapper) 
返回一个 Collector ,它产生应用于输入元素的整数值函数的和。  
static <T> Collector<T,?,Long> summingLong(ToLongFunction<? super T> mapper) 
返回一个 Collector ,它产生应用于输入元素的长值函数的和。  
static <T,C extends Collection<T>>
Collector<T,?,C> toCollection(Supplier<C> collectionFactory) 
返回一个 Collector ,按照遇到的顺序将输入元素累加到一个新的 Collection中。  
static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) 
返回一个并发的 Collector ,它将元素累加到 ConcurrentMap ,其键和值是将所提供的映射函数应用于输入元素的结果。  
static <T,K,U> Collector<T,?,ConcurrentMap<K,U>> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction) 
返回一个并发的 Collector ,它将元素累加到一个 ConcurrentMap ,其键和值是将提供的映射函数应用于输入元素的结果。  
static <T,K,U,M extends ConcurrentMap<K,U>>
Collector<T,?,M> toConcurrentMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier) 
返回一个并发的 Collector ,它将元素累加到一个 ConcurrentMap ,其键和值是将所提供的映射函数应用于输入元素的结果。  
static <T> Collector<T,?,List<T>> toList() 
返回一个 Collector ,它将输入元素 List到一个新的 List 。  
static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper) 
返回一个 Collector ,它将元素累加到一个 Map ,其键和值是将所提供的映射函数应用于输入元素的结果。  
static <T,K,U> Collector<T,?,Map<K,U>> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction) 
返回一个 Collector ,它将元素累加到 Map ,其键和值是将提供的映射函数应用于输入元素的结果。  
static <T,K,U,M extends Map<K,U>>
Collector<T,?,M> toMap(Function<? super T,? extends K> keyMapper, Function<? super T,? extends U> valueMapper, BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier) 
返回一个 Collector ,它将元素累加到一个 Map ,其键和值是将所提供的映射函数应用于输入元素的结果。  
static <T> Collector<T,?,Set<T>> toSet() 
返回一个 Collector ,将输入元素 Set到一个新的 Set 。  

6.toArray 转换成数组
Object[] toArray();

Stream的方法:
1.Stream.of(); 获取流形式的对象
2.Stream.concat(stream1, stream2) static Stream concat(Stream<? extends T> a, Stream<? extends T> b) 流合并 (会影响原对象)

流的一些操作实例

package com.youngchan.practice;

import com.sun.org.apache.xpath.internal.SourceTree;

import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author youngchan
 * @version V1.0
 * @Package com.youngchan
 * @date 2020/4/23 18:21
 */
public class Practice {
    public static void main(String[] args) {

        // 使用foreach 遍历的两种方式  方式一
        System.out.println("zero~~~~~~~~~~~~~~~~~~");
        List<String> list = new ArrayList<>();
        list.add("张无忌");
        list.add("周芷若");
        list.add("赵敏");
        list.add("张san");
        list.add(" 张 三 丰  ");
        list.forEach((a)-> System.out.println(a));
        // 方式二
        System.out.println("one~~~~~~~~~~~~~~~~~~");
        list.forEach((a)->{
            if(a.trim().startsWith("张")){
                System.out.println(a);
            }
        });
        //使用 filter进行过滤
        System.out.println("two~~~~~~~~~~~~~~~~~~");
        list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length()==4).forEach(System.out::println);


        // 使用distinct 去重 , map进行拆解筛选对象属性,collect进行收集
        System.out.println("three~~~~~~~~~~~~~~~~~~");
        list.add("张无忌");
        list.stream().filter(s -> s.trim().startsWith("张")).distinct().map(s -> s.toUpperCase()).collect(Collectors.toList()).forEach(System.out::println);

        // 使用count 统计个数
        System.out.println("four~~~~~~~~~~~~~~~~~~");
        System.out.println(list.stream().distinct().count());

        // 使用limit 过滤
        System.out.println("five~~~~~~~~~~~~~~~~~~");
        list.stream().limit(1).forEach(System.out::println);

        // 使用skip 过滤  distinct 和skip连用会用小问题(distinct不改变原集合)
        System.out.println("six~~~~~~~~~~~~~~~~~~");
        System.out.println(list.stream().distinct().collect(Collectors.toList()).stream().count());
        list.stream().distinct().collect(Collectors.toList()).stream().skip(3).limit(1).forEach(System.out::println);


        //使用concat组合  组合后会改变原集合数据
        System.out.println("seven~~~~~~~~~~~~~~~~~~");
        List<String> list2 = new ArrayList<>();
        list.add("孙悟空");
        list.add("猪八戒");
        list.add("沙和尚");
        list.add("唐三藏");
        list.add("白龙马");
        Stream<List<String>> Slist = Stream.of(list);
        Stream<List<String>> Slist2 = Stream.of(list2);
        List<List<String>> result = Stream.concat(Slist, Slist2).filter((a) -> !a.isEmpty()).distinct().collect(Collectors.toList());
        System.out.println(list2.size());
        System.out.println(list.size());
        list.forEach(System.out::println);


        // sorted 排序
        System.out.println("eight~~~~~~~~~~~~~~~~~~");
        list.stream().sorted((a,b)->a.length()-b.length()).forEach(System.out::println);


        // 是否存在 anyMath 匹配  全部是 allMatch 全匹配
        System.out.println("nine~~~~~~~~~~~~~~~~~~");
        System.out.println(list.stream().anyMatch(Predicate.isEqual("孙悟空")));
        System.out.println(list.stream().allMatch(Predicate.isEqual("孙悟空")));


        // 集合排序生成新集合
        System.out.println("ten~~~~~~~~~~~~~~~~~~");

        ArrayList<Student> students = new ArrayList<>();
        list.remove(0);
        for (int i = 0; i < list.size(); i++) {
            students.add(new Student(i+ new Random().nextInt(20),list.get(i)));
        }
        System.out.println("排序前学生集合");
        students.forEach((a)-> System.out.print(a+"   ~   "));
        System.out.println("排序后学生集合");
//        Map<Integer, String> map = students.stream().sorted((a, b) -> b.getAge() - a.getAge()).collect(Collectors.toMap(Student::getAge, Student::getName));
        Map<String, Integer> map = students.stream().sorted((a, b) -> b.getAge() - a.getAge()).collect(Collectors.toMap(Student::getName, Student::getAge));
        System.out.println(map);
        List<Student> sortedStudent = students.stream().sorted((a, b) -> a.getAge() - b.getAge()).collect(Collectors.toList());
        sortedStudent.forEach((a)-> System.out.print(a+"   ~   "));


    }

}


  城市分类Person对象: 

   Map<String, List<Person>> peopleByCity = personStream.collect(Collectors.groupingBy(Person::getCity));  以下将按国家和城市对Person对象进行分类,将两个Collector组合在一起: 

   Map<String, Map<String, List<Person>>> peopleByStateAndCity = personStream.collect(Collectors.groupingBy(Person::getState, Collectors.groupingBy(Person::getCity)));  

groupingBy  收集 按照 order_id 作为key  相同的key收集为list
 Map<String, List<Map>> orderMessageMap = orderList.stream()
          .collect(Collectors.groupingBy(a -> String.valueOf(a.get("ORDER_ID"))));

实体类

package com.youngchan.practice;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Comparator;
import java.util.Objects;

/**
 * @author youngchan
 * @version V1.0
 * @Package com.youngchan.practice
 * @date 2020/4/23 19:40
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student implements Comparator{
   private int age;
   private String name;

    @Override
    public int compare(Object o1, Object o2) {
        Student s1 = (Student) o1;
        Student s2 = (Student) o2;
        return s1.getAge()-s2.getAge();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值