JDK8新特性之Stream流

1,094 阅读5分钟

什么是Stream流

Stream不是集合元素,不是数据结构,因此不能保存数据。Stream只需给出需要对其包含的元素执行什么操作(如过滤长度符合指定长度的字符串等),Stream会隐式地在内部进行遍历,做出相应的数据转换,相当于数据在流水线上进行加工,加工后得到我们想要的数据。

几种常用的函数式接口

开始学习Stream流之前,我们需要了解几种常用的函数式接口:

  • Function函数式接口
/**
 * Function
 *有参数,有返回值
 */
public static void main(String[] args) {
    Function function = new Function<String, String>() {
        @Override
        public String apply(String str) {
            return str;
        }
    };
    
    //使用Lambda表达式简化
    Function<String, String> function2 = (str) -> {return str; };
 
    System.out.println(function2.apply("asd"));
 
}
  • Predicate 接口

image.png

/**
 * Predicate
 *有一个输入参数,返回值只能是boolean值,用于做判断
 */
 
public static void main(String[] args) {
    //可以来做判断字符串是否为空
    Predicate pc = new Predicate<String>() {
        @Override
        public boolean test(String str) {
 
            return str.isEmpty();
        }
    };
 
    System.out.println(pc.test("qwew"));
 
    //Lambda简化
    Predicate<String> pre =(str)->{return str.isEmpty(); };
    System.out.println(pre.test(""));
}
  • Customer消费型接口

image.png

/**
 * 消费型接口
 */
public class ConsumerInterface {
    public static void main(String[] args) {
        Consumer<String> stringConsumer = new Consumer<String>() {
            @Override
            public void accept(String str) {
                System.out.println(str);
            }
        };
 
        //简化
        Consumer<String> consumer =(str)->{System.out.println(str);};
        consumer.accept("打印str");
    }
}
  • Supplier供给型接口

image.png

/**
 * 供给型接口
 */
public class SupplierInterface {
    public static void main(String[] args) {
        Supplier<String> supplier = new Supplier<String>() {
            @Override
            public String get() {
                return "供给型接口";
            }
        };
 
        //简化
        Supplier<String> sp =()->{return "供给型接口";};
 
        System.out.println(sp.get());
    }

获取Stream流的方式

  • 通过Collection接口中的stream()方法获取Stream流
public interface Collection<E> extends Iterable<E> {
    default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
}
ArrayList<Integer> list = new ArrayList<>();
        
Stream<Integer> stream = list.stream();
  • 通过Stream接口中的of()静态方法获取Stream流
public interface Stream<T> extends BaseStream<T, Stream<T>> {
    @SafeVarargs
    @SuppressWarnings("varargs") // Creating a stream from an array is safe
    public static<T> Stream<T> of(T... values) {
        return Arrays.stream(values);
    }
}
Stream<String> stream = Stream.of("a","b","c","d","e");

Stream常用的API

  • Stream中方法的两种分类
  1. 终结方法,如count()、forEach()方法,如果不在最后调用Stream的终结方法,那么中间的其他非终结方法不会执行。
  2. 非终结方法(函数拼接方法),如filter()方法,非终结方法返回的是新的Stream流。

:: 双冒号的用法

:: 双冒号的作用是把方法当做参数传到stream内部,使stream的每个元素都传入到该方法里面执行一下,双冒号运算就是Java中的方法引用,其格式是为:类名::方法名

  • 如将Role实体类映射为name,在没有使用::双冒号的情况下:
stream().map((Role)->{return Role.getName();})
  • 使用双冒号后
stream().map(Role::getName})
  • 又如在Stream流中的forEeach遍历输出流中 的字符,在没有使用双冒好的情况下为:
list.stream().forEach((str)->{
    System.out.println(str);
});
  • 使用后如下:
list.stream().forEach(System.out::println);

forEach()

forEach()方法遍历流中的元素

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

Example:

 List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.stream().forEach((str)->{
            System.out.println(str);
        });
 //简写
 list.stream().forEach(System.out::println);

count()

count()方法计算流中的元素长度

long count();

filter()

筛选过滤出符合指定条件的元素

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

Example:

//筛选出值为a的元素
list.stream().filter((str)->{
    return str.equals("a");
}).forEach(System.out::println);

limit(long n)

从流中筛选出前n个元素

Stream<T> limit(long maxSize);

Example:

//筛选出流中前两个元素
list.stream().limit(2).forEach(System.out::println);

skip()

skip()方法跳过前面n个元素,获取下标为n后的元素组成的新流,如果n为0,则不会改变流中的元素个数,如果原始流中有a,b,c,d 4个元素,当n取1时,则返回包含b,c,d 3个元素的新流。

Stream<T> skip(long n);

Example:

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

map()

map()方法,将流中的元素映射到另外一个流中

//该方法需要一个Function型函数式接口,将当前流中T类型的数据转换成R类型的流
<R> Stream<R> map(Function<? super T, ? extends R> mapper);

Example:

public class User {
    private String name;
    private int age;
    private int id;
}

User u1 = new User("a", 11, 1);
User u2 = new User("b", 12, 2);
User u3 = new User("c", 24, 12);
User u4 = new User("d", 34, 4);

List<User> users = Arrays.asList(u1, u2, u3, u4);

users.stream().map((u)->{
    return u.getName()+u.getAge();
}).forEach(System.out::println);

输出:
    a11
    b12
    c24
    d34
    
(2)将原本流中类型为String的数据转换成整型数据
List<String> list = new ArrayList<>();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");

        list.stream().map((str)->{
            return Integer.parseInt(str);
        }).forEach(System.out::print);

flatMap()

flatMap()*方法,对流进行扁平化

    <R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

Example:

 String[] string = {"a","b","c","d"};
        list.stream().flatMap((str)-> Arrays.stream(string)).forEach(System.out::print);
输出:
    abcd abcd abcd abcd

sorted()

sorted()方法,对流中的数据进行排序

Stream<T> sorted();

Stream<T> sorted(Comparator<? super T> comparator);

@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);
}

Example:

List<Integer> list = new ArrayList<>();
        list.add(13);
        list.add(12);
        list.add(8);
        list.add(4);
        
        list.stream().sorted((str1,str2)->(str1-str2)).forEach(System.out::println);

distinct()

distinct()方法,去除重复数据

 Stream<T> distinct();

Example:

List<Integer> list = new ArrayList<>();
        list.add(13);
        list.add(12);
        list.add(12);
        list.add(8);
        list.add(4);
        list.add(4);

        list.stream().distinct().forEach(System.out::println);
输出:
        13
        12
        8
        4

allMatch()、anyMatch()、nonMatch()

allMatch()、anyMatch()、nonMatch()方法,判断数据是否匹配指定条件

//allMatch():元素是否全部都匹配条件
boolean allMatch(Predicate<? super T> predicate);

//anyMatch():元素是否有任意一个匹配条件
boolean anyMatch(Predicate<? super T> predicate);

//nonMatch():元素是否全部都不满足条件
boolean noneMatch(Predicate<? super T> predicate);

Example:

List<Integer> list = new ArrayList<>();
    list.add(13);
    list.add(12);
    list.add(8);
    list.add(4);

    boolean b1 = list.stream().allMatch((n) -> {return n > 8;});//false
    boolean b2 = list.stream().anyMatch((n) -> {return n > 8;});//true
    boolean b3 = list.stream().noneMatch((n) -> {return n > 8;});//false
        

findFirst()

findFirst()方法,获取流中的第一个元素

Optional<T> findFirst();

Example:

List<Integer> list = new ArrayList<>();
        list.add(13);
        list.add(12);
        list.add(8);
        list.add(4);

        Optional<Integer> first = list.stream().findFirst();
        System.out.println(first.get()); //13

findAny()

findAny()方法,返回流中随机任意一个元素

Optional<T> findAny();

Example:

List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(8);
        list.add(4);
        list.add(13);

        Optional<Integer> any = list.stream().findAny();
        System.out.println(any.get()); 

max()、min()

max()、min()方法,获取流中最大、最小的元素

Optional<T> max(Comparator<? super T> comparator);
Optional<T> min(Comparator<? super T> comparator);

Example:

List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(8);
        list.add(4);
        list.add(13);
Optional<Integer> max = list.stream().max((n1, n2) -> {
        return n1 - n2;
});

Optional<Integer> min = list.stream().min((n1, n2) -> {
        return n1 - n2;
});

System.out.println(max.get()); //13
System.out.println(min.get()); //4

reduce()

reduce()方法,将所有数据归纳得到一个总的数据

/**
* T identity :默认值
* BinaryOperator<T> accumulator 归纳数据的处理方式
**/

T reduce(T identity, BinaryOperator<T> accumulator);

//reduce()方法的第二个参数
public interface BinaryOperator<T> extends BiFunction<T,T,T> {}

@FunctionalInterface
public interface BiFunction<T, U, R> {
    R apply(T t, U u);
}

Example:

List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(8);
        list.add(4);
        list.add(13);
           
        Integer reduce = list.stream().reduce(0, new BinaryOperator<Integer>() {
            @Override
            public Integer apply(Integer integer, Integer integer2) {
                return integer+integer2;
            }
        });
        
        //以上简化得下
        Integer reduce = list.stream().reduce(0, (n1, n2) -> {
            return n1 + n2;
        });
        System.out.println(reduce); // 37 = 12 + 8 + 4 + 13

mapToInt()

mapToInt()方法,将Stream流中的Integer类型的元素转换成int类型

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

Example:

List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(8);
        list.add(4);
        list.add(13);
        
list.stream().mapToInt(new ToIntFunction<Integer>() {
            @Override
            public int applyAsInt(Integer value) {
                return value;
            }
        }).forEach(System.out::println);

concat()

concat()方法,Stream接口中的静态方法,合并两个流

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));
    }

Example:

List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(8);
        list.add(4);
        list.add(13);

        Stream<Integer> stream1 = list.stream().filter((str) -> {
            return str > 12;
        });

        Stream<Integer> stream2 = list.stream().filter((str) -> {
            return str < 5;
        });

       Stream.concat(stream1, stream2).forEach(System.out::println); //13 4

🏁以上就是对JDK8新特性Stream流的详细解释,如果有错误的地方,还请留言指正,如果觉得本文对你有帮助那就点个赞👍吧😋😻😍

默认标题_动态分割线_2021-07-15-0.gif