Stream flow operation JDK8 set of new features 6--

table of Contents

1. Stream Stream thought Overview

2. acquaintance Stream

3. Get two ways Stream stream

The acquisition stream Collection 3.1

3.2 Stream by a method of static acquisition stream

4. A common method Stream stream

Notes 4.1 Stream stream

4.1.1 Stream can only do this once

4.1.2 Stream method returns a new stream

Do not call termination method 4.1.3 Stream, the middle of the operation is not performed

4.2 forEach method

 4.3 count method

4.4 filter method

4.5 limit method

4.6 skip method

4.7 map method

4.8 sorted Methods

4.9 distinct method

4.10 match method

4.11 find method

4.12 obtain the maximum and minimum

4.13 reduce method

4.14 map Stream flows reduce in combination with

4.15 mapToInt method

4.16 static method concat method


1. Stream Stream thought Overview

        Stream flow idea is similar to the factory floor "production line", Stream flow is not a data structure, the data is not saved, but the data processing. Stream can be seen as a step in the pipeline, on the assembly line, by a plurality of steps so that raw materials into a product.

Stream flow will allow us to quickly accomplish many complex operations, such as filtering, slicing, mapping, search, de-emphasis, statistics, match and protocols and so on.

Note: There is no relationship with the IO Stream flow stream.

2. acquaintance Stream

        Stream is a functional programming mode on the collection tool complicated operation, which integrates the operation of one of the many new features of polymerization in 8 Java, developers can more easily using a Lambda expression, and more easily achieved Find a collection of traversal, filter and common computing.

Let's look at a demand to find objects that meet certain requirements in the list <Oject> set and converted into a list <String> collection

Practice before JDK1.8 are:

private static List<String> getDishNameByList(List<Dish> dishs){
        List<Dish> list = new ArrayList<>();
        for(Dish d : dishs){
            if(d.getCalories() < 400){
                list.add(d);
            }
        }
        Collections.sort(list,(dish1,dish2) -> Integer.compare(dish1.getCalories(),dish2.getCalories()));
        List<String> names = new ArrayList<>();
        for(Dish d : list){
            names.add(d.getName());
        }
        return names;
    }

Use stream approach:

private static List<String> getDishNameByStream(List<Dish> dishs){
        List<String> collect = dishs.stream().filter(d -> d.getCalories() < 400)
                .sorted(Comparator.comparing(Dish::getCalories)).map(Dish::getName)
                .collect(toList());
        return collect;
    }

3. Get two ways Stream stream

The acquisition stream Collection 3.1

There is a default interface method in Collection: default Stream <E> stream ()

By definition, all interfaces can know Collection interface has a stream method, for example:

public class StreamDemo1 {
    public static void main(String[] args) {
        List list = new ArrayList();
        Stream stream = list.stream();

        Set set = new HashSet();
        Stream stream1 = set.stream();

        Map map = new HashMap();
        Stream stream2 = map.keySet().stream();
        Stream stream3 = map.values().stream();
        Stream stream4 = map.entrySet().stream();
    }
}

Note: Map Collection interface does not belong to the sub-interface, so there is no stream class Map implementation method, but examples of the acquired key map and set value is set Collection subclass stream method can be used.

3.2 Stream by a method of static acquisition stream

static <T> Stream<T> of(T... values)

Can know the nature of accepting a type of variable parameters, variable parameter is an array, that is to say, can also accept an array parameter, for example:

public static void main(String[] args) {
   Stream<String> stream = Stream.of("aa", "bb", "cc");

   Integer[] arrar = {1, 2, 2, 3, 4, 5};
   Stream<Integer> objectStream = Stream.of(arrar);
}

Note: an array of basic data types can not be used in this way fluidized example:

int[] arr = {1, 2, 2, 3, 4, 5};
Stream<int[]> stream1 = Stream.of(arr);

For an array of type int above, when using the method of the Stream fluidized, is the entire int [] object to be seen as an operation without operation of elements in the array, if the generic int [] into int The compiler will error.

4. A common method Stream stream

Stream flow operating model is very rich, providing a lot of useful API, roughly be divided into two

1) End of method: the return value type is no longer Stream, is no longer supported chained calls,

2) non-terminal method: return type is still Stream, to support chained calls (except for the end of the method, the rest are non-termination method)

The following are some simple methods commonly used:

Method name Methods role Return Type Methods species
count The number of statistics long End
forEach One by one process void End
filter filter Stream Stitching function
limit Access to the first few Stream Stitching function
skip Skip a few ago Stream Stitching function
map Mapping Stream Stitching function
concat combination Stream Stitching function

Notes 4.1 Stream stream

4.1.1 Stream can only do this once

E.g:

Stream<String> stream = Stream.of("aa", "bb", "cc");
stream.count();
stream.count();

For stream flow object, if the method is called only once count will not go wrong if you call twice to above, it will be given the wrong information is as follows:

4.1.2 Stream method returns a new stream

For example: return value of false

Stream<String> stream = Stream.of("aa", "bb", "cc");
Stream<String> limit = stream.limit(1);
System.out.println(stream == limit);

Do not call termination method 4.1.3 Stream, the middle of the operation is not performed

E.g:

public static void main(String[] args) {
    Stream<String> stream = Stream.of("aa", "bb", "cc");
    stream.filter((s) -> {
         System.out.println(s);
         return true;
    });
}

When we just call the stitching function of the filter Stream, print statements will never be executed, it is necessary to call the end method to perform print statements, such as:

public static void main(String[] args) {
    Stream<String> stream = Stream.of("aa", "bb", "cc");
    stream.filter((s) -> {
         System.out.println(s);
         return true;
    }).count();
}

4.2 forEach method

forEach method for traversing data stream, the method is defined

void forEach(Consumer<? super T> var1);

该方法接收一个Consumer接口函数,会将每一个元素交给该函数进行处理。

例如:

public static void main(String[] args) {
	List<String> list = new ArrayList<String>();
	Collections.addAll(list,"a","b","c","d","e","f");

	list.stream().forEach(s->{
	    System.out.println(s);
	});

	// 上面的Lambda可以改成下面的方法引用的形式
	list.stream().forEach(System.out::println);

}

同时我们也可以使用另一个集合去接收这个集合中的元素

List l = new ArrayList();
list.stream().forEach(l::add);

注意:对于foreach方法,可以不使用stream转换,例如;

public static void main(String[] args) {
	List<String> list = new ArrayList<String>();
	Collections.addAll(list,"a","b","c","d","e","f");

	list.forEach(s->{
	    System.out.println(s);
	});

	// 上面的Lambda可以改成下面的方法引用的形式
	list.forEach(System.out::println);

}

 4.3 count方法

Stream流提供count方法来统计其中的元素个数,方法定义为:long count(),该方法返回一个long值代表元素个数,

例如:

long count = list.stream().count();

4.4 filter方法

filter用于过滤数据,返回符合条件的数据,在开发中,我们可以通过filter将一个流转换成另一个子集流,方法声明:

Stream<T> filter(Predicate<? super T> var1);

该接口接收一个Predicate函数式接口参数(可以是一个Lambda或方法引用)作为筛选条件。

例如:

list.stream().filter( s -> s.indexOf("h") != -1 ).forEach(System.out::println);

注意:Lambda表达式,当只有一句话的return语句的时候,可以省略大括号省略return。

4.5 limit方法

limit方法可以对流进行截取,只取用前N个,方法定义:Stream<T> limit(long var1);

参数是long型,如果集合当前长度大于参数则进行截取,否则不进行操作。

例如:

list.stream().limit(4).forEach(System.out::println);

4.6 skip方法

如果希望跳过前几个元素,可以使用skip方法获取一个截取之后的新流,方法定义为:Stream<T> skip(long n),如果当流的当前长度大于n,则跳过前n个,否则将会得到一个长度为0的空流。

例如:

list.stream().skip(4).forEach(System.out::println);

4.7 map方法

如果需要将流的元素映射到另一个流中,可以使用map方法,方法定义为:

<R> Stream<R> map(Function<? super T, ? extends R> var1);

该接口需要一个Function函数式接口参数,可以将当前流中的T类型的数据转换为另一种R类型的流。

例如:map将一个String流转成了Integer流

Stream<String> strStream = list.stream();
Stream<Integer> stream = strStream.map(Integer::parseInt);

4.8 sorted方法

如果需要将数据排序,可以使用sorted方法,方法定义为

Stream<T> sorted();  // 自然顺序排序

Stream<T> sorted(Comparator<? super T> var1);  // 自定义排序

例如:

public class StreamSorted {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        Collections.addAll(list,1,5,2,4,8,10);
        list.stream().sorted()  // 自然顺序排序
                .sorted((i1,i2) -> i2-i1)   // 降序排序
                .forEach(System.out::println);
    }
}

4.9 distinct方法

如果需要去除重复数据,可以使用distinct方法,方法定义:Stream<T> diatinct(),例如:

list.stream().distinct().forEach(System.out::println);

注意:对于自定义类型的数据,去重需要类对象重写hashCode与equals方法。

4.10 match方法

如果需要判断数据是否匹配指定的条件,可以使用match相关方法,方法定义

boolean anyMatch(Predicate<? super T> var1);    // 匹配任意一个,只要有一个满足指定条件就可以

boolean allMatch(Predicate<? super T> var1);    // 匹配所有元素,元素是否全部满足指定条件

boolean noneMatch(Predicate<? super T> var1);    // 匹配所有元素,所有元素都不满足指定条件

例如:

package com.bjc.jdk8.stream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class StreamMatch {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        Collections.addAll(list,1,5,2,4,8,10);
        boolean b = list.stream().allMatch(i -> i > 0);
        System.out.println(b);
        boolean b1 = list.stream().anyMatch(i -> i > 5);
        System.out.println(b1);
        boolean b2 = list.stream().noneMatch(i -> i < 0);
        System.out.println(b2);
    }
}

返回结果均为true。

4.11 find方法

如果需要找到某些数据,可以使用find相关方法,方法定义:

Optional<T> findFirst();

Optional<T> findAny();

注意:这两个方法都是查找流中的第一个元素

例如:

package com.bjc.jdk8.stream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class StreamFind {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        Collections.addAll(list,1,5,2,4,8,10);

        Integer integer = list.stream().findFirst().get();
        System.out.println(integer);

        Integer integer1 = list.stream().findAny().get();
        System.out.println(integer1);
    }
}

输出结果都是1

4.12 获取最大最小值

如果需要获取最大值和最小值,可以使用max和min方法,方法定义:

Optional<T> min(Comparator<? super T> var1);

Optional<T> max(Comparator<? super T> var1);

例如:

public static void main(String[] args) {
	List<Integer> list = new ArrayList<Integer>();
	Collections.addAll(list,1,5,2,4,8,10);

	Integer integer = list.stream().max((o1,o2) -> o1 - o2).get();
	System.out.println(integer);

	Integer integer1 = list.stream().min((o1,o2) -> o1 - o2).get();
	System.out.println(integer1);
}

4.13 reduce方法

如果需要将所有数据归纳得到一个数据,可以使用reduce方法,方法定义:

T reduce(T var1, BinaryOperator<T> var2);

第一个参数:默认值

第二个参数:数据处理逻辑,BinaryOperator继承自BiFunction,且BinaryOperator接口中无抽象的方法,所以,找父类的BiFunction的抽象方法

R apply(T var1, U var2);

例如:带默认值的reduce

package com.bjc.jdk8.stream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;

public class StreamReduce {
    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(1, 3, 4, 5, 2, 7, 9);

        Integer reduce = stream.reduce(0, (x, y) -> x + y);
        System.out.println(reduce);
    }
}

或者,不带默认值的reduce

package com.bjc.jdk8.stream;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;

public class StreamReduce {
    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(1, 3, 4, 5, 2, 7, 9);

        Optional<Integer> reduce = stream.reduce((x, y)->x+y);

        System.out.println(reduce.get());
    }
}

4.14 Stream流的map与reduce组合使用

通过Stream流的map与reduce的组合使用可以大大的简化我们对集合的操作

例如:定义如下对象流

Stream<Person> stream = Stream.of(
                new Person("张三",22),
                new Person("李四",23),
                new Person("王五",21),
                new Person("赵六",26),
                new Person("钱七",25)
        );

1)求出所有的年龄之和

// Integer reduce = stream.map(p->p.getAge()).reduce(0, (x, y) -> x+y);
Integer reduce1 = stream.map(Person::getAge).reduce(0, (x, y) -> x + y);
System.out.println(reduce);

注意:因为Integer有一个sum方法可以求和,所以,上面的代码还可以改成如下形式:

Integer reduce1 = stream.map(Person::getAge).reduce(0, Integer::sum);

2)找出最大年龄

Optional<Integer> reduce = stream.map(Person::getAge).reduce(Integer::max);
Integer integer = reduce.get();
System.out.println(integer);

3)统计一个流中a出现的次数

例如:

 Stream<String> stream1 = Stream.of(
                "a","b","c","a","a","f","a","d"
        );
Optional<Integer> option = stream1.map(str -> "a".equals(str) ? 1 : 0).reduce(Integer::sum);
Integer integer = option.get();
System.out.println(integer);

4.15 mapToInt方法

如果需要将Stream<Integer>中的Integer类型数据转换成int类型,可以使用mapToInt方法,方法定义为:

IntStream mapToInt(ToIntFunction<? super T> mapper);

我们为什么要将Integer流转成int了,这是因为Integer占用的内存比int多,在Stream流操作中会自动装箱和拆箱,经过mapToInt方法转换之后,就将一个Integer类型的stream转成了一个IntStream,那么这个IntStream流与Stream流有什么关系了?如下图所示,两者有一个父接口Basestream,只是IntStream内部操作的是int数据,可以节省内存,减少自动拆箱装箱。

例如:

public class StreamMapToInt {
    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
        IntStream intStream = stream.mapToInt(Integer::intValue);
        intStream.forEach(System.out::println);
    }
}

4.16 静态方法concat方法

如果有两个流,希望合并成为一个流,那么可以使用Stream接口的静态方法concat,方法定义:

public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
     Objects.requireNonNull(a);
     Objects.requireNonNull(b);

     @SuppressWarnings("unchecked")
     Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>(
                (Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator());
        Stream<T> stream = StreamSupport.stream(split, a.isParallel() || b.isParallel());
      return stream.onClose(Streams.composedClose(a, b));
}

例如:

public class StreamConcat {
    public static void main(String[] args) {
        Stream<String> stream = Stream.of("张三", "李四", "王五", "赵六");
        Stream<String> stream1 = Stream.of("钱七", "朱八", "宫九");
        Stream<String> concat = Stream.concat(stream, stream1);
        concat.forEach(System.out::println);
    }
}

注意:当使用concat合并流之后,合并之前的流不能使用了,否则会报如下错

发布了205 篇原创文章 · 获赞 9 · 访问量 7918

Guess you like

Origin blog.csdn.net/weixin_43318134/article/details/104426833