Stream流的常用方式

一、Stream流常见用法

  1. Stream流生成的方式
  • Collection集合生成流
List<String> str = new ArraryList<>();
Stream<String> stream = str.stream();
  • Map集合生成流
Map<String,String> maps = new HashMap();
Stream<String> strMap = maps.keySet().stream();
Stream<String> strMap = maps.values().stream();
  • 数组生成流
Integer[] arr = {2,3,5,3,4,2};
Stream<Integer> array = Stream.of(arr);
  1. Stream流中间方法
  • Filter()
ArrayList<String> names = new ArrayList<String>();
names.add("张三");
names.add("李四");
names.add("王五");
names.add("张三丰");
names.stream().filter(s -> s.length()>2).forEach(s -> System.out.println("name:"+s));

输出结果:name:张三丰

List<Person> personList = new ArrayList<>();
Person person = new Person();
person.setName("zhangsan");
person.setAge(20);
personList.add(person);
Person person1 = new Person();
person1.setName("lisi");
person1.setAge(22);
Person person2  = new Person();
person2.setName("wangwun");
person2.setAge(33);
personList.add(person1);
personList.add(person2);
personList.stream().filter(s->s.getAge()>22).forEach(s-> System.out.println("person:"+s));

输出结果:person:Person{name='wangwun', age=33}

  • Limit()
ArrayList<String> names = new ArrayList<String>();
names.add("张三");
names.add("李四");
names.add("王五");
names.add("张三丰");
names.stream().limit(2).forEach(s -> System.out.println("names:"+s));

输出结果:names:张三
names:李四

  • Skip():
ArrayList<String> names = new ArrayList<String>();
names.add("张三");
names.add("李四");
names.add("王五");
names.add("张三丰");
names.stream().skip(2).forEach(s -> System.out.println("names:"+s));

输出结果:names:王五
names:张三丰

  • Sorted():
ArrayList<String> names = new ArrayList<String>();
names.add("张三");
names.add("李四");
names.add("王五");
names.add("张三丰");
names.add("李四");
names.stream().sorted((s1,s2)->{return s1.length()-s2.length();}).forEach(s -> System.out.println("姓名:"+s));

输出结果:
姓名:张三
姓名:李四
姓名:王五
姓名:李四
姓名:张三丰

  • Distinct():
ArrayList<String> names = new ArrayList<String>();
names.add("张三");
names.add("李四");
names.add("王五");
names.add("张三丰");
names.add("李四");
names.stream().distinct().forEach(s -> System.out.println("name:"+s));

输出结果:
name:张三
name:李四
name:王五
name:张三丰

  • Concat():
ArrayList<String> names = new ArrayList<String>();
ArrayList<String> names2 = new ArrayList<>();
names.add("张三");
names.add("李四");
names2.add("王五");
names2.add("张三丰");
Stream<String> stream = names.stream();
Stream<String> stream1 = names2.stream();
Stream.concat(stream,stream1).forEach(s -> System.out.println("name:"+s));

输出结果:
name:张三
name:李四
name:王五
name:张三丰

  • Map()
    转换对象类型
List<Long> matterIdList = tczWgrTaskList.stream().map(TWgrTask::getMatterId).collect(Collectors.toList());
  1. Stream流收集方法
  • Collect()
    获取对象集合中某个对象字段的集合
 List<Long> matterIdList = tczWgrTaskList.stream().map(TWgrTask::getMatterId).collect(Collectors.toList());

根据对象的某个字段分组获取这个字段对应的对象集合

 Map<Long, List<TWgrTask>> wgrTaskMap = czWgrTaskList.stream().collect(Collectors.groupingBy(TWgrTask::getSpecialId));

获取对象集合过滤后的集合数据

List<TaskResult> taskResults = taskResultList.stream().filter(taskResult -> inspectItem.getId().equals(taskResult.getInspectId()) ).collect(Collectors.toList());

根据对象集合转为某个字段对应对象的键值对

Map<Long, TWgrTask> wgrTaskMap = czWgrTaskList.stream().collect(Collectors.toMap(TWgrTask::getMatterId, t -> t));

二、函数式接口
概述:有且仅有一个抽象方法的接口
可以使用@FunctionalInterface注解验证是否是函数式接口,如果是则编译通过
如果式函数式接口做参数或返回值可以使用lambda表达式和方法引用符,因为符合可推导可省略的原则
三、Supplier接口
Supplier:包含一个无参的方法

  • 是一个生产型的接口
  • T get() :获得结果
  • 该方法不需要参数,会按照某种实现逻辑返回一个数据
  • 如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会返回什么类型的数据供我们使用
import java.util.function.Supplier;

public class MyFunctionDemo2 {
    public static void main(String[] args) {
        Integer s = getInt(() -> 2 + 3);
        System.out.println(s);
    }

    public static Integer getInt(Supplier<Integer> sup) {
        return sup.get();
    }
}

打印:5

四、Consumer接口
Consumer:包含两个方法

  • void accept(T t):对给定的参数执行此操作
  • default Consumer andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作
  • Consumer接口也被称为消费型接口,它消费的数据的数据类型由泛型指定

Stream流的forEach方法使用的Consumer作为参数遍历集合中每个数据

 @Override
        public void forEach(Consumer<? super E_OUT> action) {
            if (!isParallel()) {
                sourceStageSpliterator().forEachRemaining(action);
            }
            else {
                super.forEach(action);
            }
        }

五、Predicate接口
Predicate:常用的四个方法

  • boolean test(T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
  • default Predicate negate():返回一个逻辑的否定,对应逻辑非
  • default Predicate and(Predicate other):返回一个组合判断,对应短路与
  • default Predicate or(Predicate other):返回一个组合判断,对应短路或
import java.util.function.Consumer;
import java.util.function.Predicate;

public class MyFunctionDemo3 {
    public static void main(String[] args) {
        ArrayList<String> names = new ArrayList<String>();
        names.add("张三");
        names.add("李四");
        names.add("王五");
        names.add("张三丰");
        names.add("李四");
        boolean b =  checkString(names,strings -> strings.size()>0);
        System.out.println(b);
    }

    private static boolean checkString(List<String> strings, Predicate<List<String>> predicate){
        return predicate.test(strings);
    }
}

Stream流的filter方法使用的就是Predicate接口

    @Override
    public final Stream<P_OUT> filter(Predicate<? super P_OUT> predicate) {
        Objects.requireNonNull(predicate);
        return new StatelessOp<P_OUT, P_OUT>(this, StreamShape.REFERENCE,
                                     StreamOpFlag.NOT_SIZED) {
            @Override
            Sink<P_OUT> opWrapSink(int flags, Sink<P_OUT> sink) {
                return new Sink.ChainedReference<P_OUT, P_OUT>(sink) {
                    @Override
                    public void begin(long size) {
                        downstream.begin(-1);
                    }

                    @Override
                    public void accept(P_OUT u) {
                        if (predicate.test(u))
                            downstream.accept(u);
                    }
                };
            }
        };
    }

六、Function接口
Function<T,R>:
是一个 类型转换型 的接口

  • R apply(T t):将此函数应用于给定的参数
  • default Function andThen(Function after):返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
  • Function<T,R>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值,方法中的泛型T,R
  • T:转换前的数据类型
  • R:转换后的数据类型
public static void main(String[] args) {
    conver("100",s->Integer.parseInt(s));
}
public static void conver(String s, Function<String,Integer> fun){
    System.out.println(fun.apply(s));
}

Stream流中map方法使用的式Funciton接口进行操作,将流原类型转为参数数据的类型

    @Override
    @SuppressWarnings("unchecked")
    public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
        Objects.requireNonNull(mapper);
        return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
                                     StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
            @Override
            Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
                return new Sink.ChainedReference<P_OUT, R>(sink) {
                    @Override
                    public void accept(P_OUT u) {
                        downstream.accept(mapper.apply(u));
                    }
                };
            }
        };
    }
posted @ 2020-11-16 15:10  早睡身体好8  阅读(181)  评论(0)    收藏  举报