天天看点

java 8 Stream流大全,讲解java 8 stream源码内容

写这篇文章,主要是记录java8 stream流的用法,博主也是查阅了一些资料,结合源码总结出stream流的主要用法,篇幅比较长,需要耐心看。

目录

filter过滤

map获取属性并return值

mapToInt mapToLong mapToDouble 

flatMap

distinct

sorted

of

peek

limit和skip

forEach

toArray

min

anyMatch ,allMatch ,noneMatch 匹配

Reduce

collect

partitioningBy和groupingBy

Collectors.counting,maxBy,averagingInt

Collectors.collectingAndThen

Collectors.toMap

findAny ,findFirst

filter过滤

 Stream<T> filter(Predicate<? super T> predicate)
           
public interface Predicate<T> {
    boolean test(T t);

    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

     static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}
           

demo:

List<Person> personList = new ArrayList<>();
        personList.add(new Person("xiaoming", 21, "男"));
        personList.add(new Person("xiaoming", 21, "男"));
        personList.add(new Person("duwea1", 13, "男"));
        personList.add(new Person("ewwwea1", 34, "男"));

        personList.stream().filter(person -> person.getAge()>30).forEach(person -> System.out.println(person));
           

输出:

Person[name='ewwwea1', age=34, sex='男']
           

map获取属性并return值

<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Function function = new Function<Person, Object>() {
    @Override
    public Object apply(Person person) {
        return person.getName();
    }

    @Override
    public <V> Function<V, Object> compose(Function<? super V, ? extends Person> before) {
        return null;
    }

    @Override
    public <V> Function<Person, V> andThen(Function<? super Object, ? extends V> after) {
        return null;
    }
};
           
List<String> list= (List<String>) personList.stream().map(Person::getName).collect(Collectors.toList());
           

mapToInt mapToLong mapToDouble 

IntStream mapToInt(ToIntFunction<? super T> mapper);
LongStream mapToLong(ToLongFunction<? super T> mapper);
DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper);
           

 这三个可以借助求和,求平均值,最大值最小值等

Integer sum = personList.stream().mapToInt(person -> person.getAge()).sum();
double average = personList.stream().mapToInt(person -> person.getAge()).average().getAsDouble();
System.out.println(sum);
System.out.println(average);
System.out.println(average);
           

flatMap

<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);
IntStream flatMapToInt(Function<? super T, ? extends IntStream> mapper);
LongStream flatMapToLong(Function<? super T, ? extends LongStream> mapper);
DoubleStream flatMapToDouble(Function<? super T, ? extends DoubleStream> mapper);
           

map和fllatmap区别:

map:map方法返回的是一个object,map将流中的当前元素替换为此返回值;

flatMap:flatMap方法返回的是一个stream,flatMap将流中的当前元素替换为此返回流拆解的流元素;

distinct

返回由不同元素组成的流(根据
 {@link Object#equals(Object)}) 这个流。
Stream<T> distinct();
简单去重方法
List<Person> personList = new ArrayList<>();
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("xiaoming", 21, "男"));
personList.add(new Person("duwea1", 13, "男"));
personList.add(new Person("ewwwea1", 34, "男"));
personList =personList.stream().distinct().collect(Collectors.toList());
           

sorted

排序
返回由该流的元素组成的流,按照自然顺序排序。 如果此流的元素不是 {@code Comparable},则在执行终端操作时可能会抛出 {@code java.lang.ClassCastException}。
Stream<T> sorted();
返回由该流的元素组成的流,根据提供的 {@code Comparator} 进行排序。
Stream<T> sorted(Comparator<? super T> comparator);
 
/*正序*/
List<User> Asclist = userList.stream().sorted(Comparator.comparingInt(User::getId)).collect(Collectors.toList());
/*倒序*/
List<User> DescList = userList.stream().sorted(Comparator.comparingInt(User::getId).reversed()).collect(Collectors.toList());
           

of

String[] strings = {"java","python","Math","go","c","c++"};
        Stream.of(strings).forEach(System.out::println);
           

peek

返回一个由该流的元素组成的流,另外在每个元素上执行提供的操作,因为元素从结果流中被消耗。
Stream<T> peek(Consumer<? super T> action);
看下Consumer方法:
@FunctionalInterface
public interface Consumer<T> {
    void accept(T t);
    
    default Consumer<T> andThen(Consumer<? super T> after) {
    Objects.requireNonNull(after);
    return (T t) -> { accept(t); after.accept(t); };
}
           

limit和skip

Stream<T> limit(long maxSize);
限制数据量返回由该流的元素组成的流,长度被截断为不超过 maxSize

返回由该流的其余元素组成的流
 在丢弃流n个元素之后,如果此流包含少于n个元素,则将返回一个空流。
Stream<T> skip(long n);
           

forEach

对此流的每个元素执行一个操作,就是遍历元素
void forEach(Consumer<? super T> action);
如果流具有定义的顺序,则按顺序对此流的每个元素执行操作。
void forEachOrdered(Consumer<? super T> action);
           

toArray

返回一个包含此流元素的数组。
Object[] toArray()
返回一个包含此流元素的数组,使用提供了 {@code generator} 函数来分配返回的数组,以及分区执行或调整大小可能需要的任何其他数组。
<A> A[] toArray(IntFunction<A[]> generator);
public interface IntFunction<R> {R apply(int value);}
           

min

Integer[] integers ={22,12,1,2,3,11,221};
        Optional optional = Stream.of(integers).min(Comparator.comparing((Integer::shortValue)));
        System.out.println(optional.get());
           

anyMatch ,allMatch ,noneMatch 匹配

/**
         * 部分匹配
         */
        boolean rs  = personList.stream().anyMatch(new Predicate<Person>() {
            @Override
            public boolean test(Person person) {
                return person.getAge() > 10;
            }
        });
        System.out.println(rs);

        /**
         * 全部匹配
         */
        boolean rs1  = personList.stream().allMatch(new Predicate<Person>() {
            @Override
            public boolean test(Person person) {
                return person.getAge() > 30;
            }
        });
        System.out.println(rs1);

        /**
         * 全部不匹配
         */
        boolean rs2  = personList.stream().noneMatch(new Predicate<Person>() {
            @Override
            public boolean test(Person person) {
                return person.getAge() > 30;
            }
        });
        System.out.println(rs2);
           

Reduce

Reduce 原意:减少,缩小 根据指定的计算模型将Stream中的值计算得到一个最终结果

Optional<T> reduce(BinaryOperator<T> accumulator);
对Stream中的数据通过累加器accumulator迭代计算,最终得到一个Optional对象
Optional optional = personList.stream().map(person -> person.getAge()).reduce((a, b)->{
     return a+b;
 });
           
T reduce(T identity, BinaryOperator<T> accumulator);
提供一个跟Stream中数据同类型的初始值identity,通过累加器accumulator迭代计算Stream中的数据,得到一个跟Stream中数据相同类型的最终结果
           

 demo:

List<Person> personList = new ArrayList<>();
        personList.add(new Person("xiaoming", 21, "男"));
        personList.add(new Person("xiaoming", 21, "男"));
        personList.add(new Person("duwea1", 13, "男"));
        personList.add(new Person("ewwwea1", 34, "男"));


        Integer optional = personList.stream().map(Person::getAge).reduce(10, (a, b) -> {
            System.out.printf("a:%d \n", a);
            System.out.printf("b:%d \n", b);
            a += b;
            System.out.printf("a: %d \n", a);
            return a;
        });
        System.out.println("result:" + optional);
           

输出结果:

a:10 
b:21 
a: 31 
a:31 
b:21 
a: 52 
a:52 
b:13 
a: 65 
a:65 
b:34 
a: 99 
result:99
           
<U> U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator<U> combiner);
首先看一下BiFunction的三个泛型类型分别是U、 ? super T、U,参考BiFunction函数式接口apply方法定义可以知道,累加器累加器通过类型为U和? super T的两个输入值计算得到一个U类型的结果返回。也就是说这种reduce方法,提供一个不同于Stream中数据类型的初始值,通过累加器规则迭代计算Stream中的数据,最终得到一个同初始值同类型的结果
           

demo:

List<Person> personList = new ArrayList<>();
        personList.add(new Person("xiaoming", 21, "男"));
        personList.add(new Person("xiaoming", 21, "男"));
        personList.add(new Person("duwea1", 13, "男"));
        personList.add(new Person("ewwwea1", 34, "男"));


        ArrayList<Integer> newList = new ArrayList<>();

        ArrayList<Integer> accResult_ = Stream.of(10, 11, 12)
                .reduce(newList,
                        (acc, item) -> {
                            acc.add(item);
                            System.out.println("item: " + item);
                            System.out.println("acc+ : " + acc);
                            return acc;
                        }, (acc, item) -> {
                          return null;
                        });
        System.out.println("accResult_: " + accResult_);
        System.out.println("newList:" + newList);
           

 输出:

item: 10
acc+ : [10]
item: 11
acc+ : [10, 11]
item: 12
acc+ : [10, 11, 12]
accResult_: [10, 11, 12]
newList:[10, 11, 12]
           

collect

<R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);
           
<R, A> R collect(Collector<? super T, A, R> collector);
           

我们主要用Collector的方法 ,简单介绍几个Collectors应用方法

  • 转换为集合
public static <T>
    Collector<T, ?, Set<T>> toSet() {
        return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_UNORDERED_ID);
    }


    public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }

    public static <T, C extends Collection<T>>
    Collector<T, ?, C> toCollection(Supplier<C> collectionFactory) {
        return new CollectorImpl<>(collectionFactory, Collection<T>::add,
                                   (r1, r2) -> { r1.addAll(r2); return r1; },
                                   CH_ID);
    }
           

 demo:

List<String> list = Arrays.asList("java", "python","python", "C++","php","java");
        list = list.stream().collect(Collectors.toList());
        Set<String> strings =list.stream().collect(Collectors.toSet());
        
        //用LinkedList收集
        List<String> linkedListResult = list.stream().collect(Collectors.toCollection(LinkedList::new));
        linkedListResult.forEach(System.out::println);
        System.out.println("--------------");

        //用CopyOnWriteArrayList收集
        List<String> copyOnWriteArrayListResult = list.stream().collect(Collectors.toCollection(CopyOnWriteArrayList::new));
        copyOnWriteArrayListResult.forEach(System.out::println);
        System.out.println("--------------");

        //用TreeSet收集
        TreeSet<String> treeSetResult = list.stream().collect(Collectors.toCollection(TreeSet::new));
        treeSetResult.forEach(System.out::println);
           
  • Collectors.joining方法 

public static Collector<CharSequence, ?, String> joining() {
        return new CollectorImpl<CharSequence, StringBuilder, String>(
                StringBuilder::new, StringBuilder::append,
                (r1, r2) -> { r1.append(r2); return r1; },
                StringBuilder::toString, CH_NOID);
    }


    public static Collector<CharSequence, ?, String> joining(CharSequence delimiter) {
        return joining(delimiter, "", "");
    }

    public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
                                                             CharSequence prefix,
                                                             CharSequence suffix) {
        return new CollectorImpl<>(
                () -> new StringJoiner(delimiter, prefix, suffix),
                StringJoiner::add, StringJoiner::merge,
                StringJoiner::toString, CH_NOID);
    }
           

 demo:

List<String> list = Arrays.asList("java", "python", "python", "C++", "php", "java");


        String result = list.stream().collect(Collectors.joining(",","[ "," ]"));
        System.out.println(result);
           

输出:

[ java,python,python,C++,php,java ]
           

partitioningBy和groupingBy

// groupingBy 用于分组 
 Map<String,List<Person>> map = personList.stream().collect(Collectors.groupingBy(Person::getName));

        System.out.println(map);

      //partitioningBy 用于分隔

        Map<Boolean,List<Person>> map1 = personList.stream().collect(Collectors.partitioningBy(p->{return p.getAge()>30;}));
        System.out.println(map1);
           

输出结果:

{duwea1=[Person[name='duwea1', age=13, sex='男']], xiaoming=[Person[name='xiaoming', age=21, sex='男'], Person[name='xiaoming', age=21, sex='男']], ewwwea1=[Person[name='ewwwea1', age=34, sex='男']]}
{false=[Person[name='xiaoming', age=21, sex='男'], Person[name='xiaoming', age=21, sex='男'], Person[name='duwea1', age=13, sex='男']], true=[Person[name='ewwwea1', age=34, sex='男']]}
           

Collectors.counting,maxBy,averagingInt

/**
         * 计数
         */
        Long count = list.stream().collect(Collectors.counting());
        System.out.println(count);

        /**
         * 年龄最大的数据
         */
        Optional<Person> person = personList.stream().collect(Collectors.maxBy(Comparator.comparing(Person::getAge)));
        if (person.isPresent()) {
            System.out.println(person.get());
        }

        /**
         * 平均值
         */
        double age = personList.stream().collect(Collectors.averagingInt(Person::getAge));
        System.out.println("平均年龄:" + age);
           

Collectors.collectingAndThen

/**
         * 根据属性去重
         */
        personList = personList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(
                () -> new TreeSet<>(Comparator.comparing(Person::getName))), ArrayList::new));
           

Collectors.toMap

tomap方法:
toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper);
toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,
        BinaryOperator<U> mergeFunction);
toMap(Function<? super T, ? extends K> keyMapper, Function<? super T, ? extends U> valueMapper,
        BinaryOperator<U> mergeFunction, Supplier<M> mapSupplier);

参数讲解:
keyMapper:Key 的映射函数
valueMapper:Value 的映射函数
mergeFunction:当 Key 冲突时,调用的合并方法
mapSupplier:Map 构造器,在需要返回特定的 Map 时使用
           

demo: 

List<Person> personList = new ArrayList<>();
        personList.add(new Person("xiaoming", 21, "男"));
        personList.add(new Person("xiaoming", 21, "男"));
        personList.add(new Person("duwea1", 13, "男"));
        personList.add(new Person("ewwwea1", 34, "男"));

        Map<String, Integer> map = personList.stream().collect(Collectors.toMap(Person::getName, Person::getAge, (v1,v2)->v1+v2, TreeMap::new));

        System.out.println("map合并后:"+map);
           

 Collectors的一些方法介绍:

java 8 Stream流大全,讲解java 8 stream源码内容

findAny ,findFirst

/**
         * 查看第一个
         */
        Optional optional = personList.stream().findFirst();
        if (optional.isPresent()) {
            System.out.println(optional.get());
        }

        /**
         * 随机查看
         */
        Optional optional1 = personList.stream().findAny();
        if (optional1.isPresent()) {
            System.out.println(optional1.get());
        }