Java JDK8 新特性 Lambda 函数式接口 streamAPI





【Lambda表达式】

Lambda表达式:带有参数变量的表达式,是一段可以传递的代码,可以被一次或多次执行,是一种精简的字面写法,其实就是把匿名内部类中“一定”要做的工作省略掉,然后由JVM通过推导把简化的表达式还原

格式:->可理解为“被用于”的意思

(参数) -> 表达式或方法体

示例

(int a, int b) -> {  return a + b; }

() -> System.out.println("Hello World");

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

() -> 42

() -> { return 3.1415 };

Lambda 表达式的结构

- Lambda 表达式可以具有零个,一个或多个参数。

- 可以显式声明参数的类型,也可以由编译器自动从上下文推断参数的类型。例如`(int a)` 与刚才相同 `(a)`。

- 参数用小括号括起来,用逗号分隔。例如 `(a, b)` 或 `(int a, int b)` 或 `(String a, int b, float c)`。

- 空括号用于表示一组空的参数。例如 `() -> 42`。

- 当有且仅有一个参数时,如果不显式指明类型,则不必使用小括号。例如 `a -> return a*a`。

- Lambda 表达式的正文可以包含零条,一条或多条语句。

- 如果 Lambda 表达式的正文只有一条语句,则大括号可不用写,且表达式的返回值类型要与匿名函数的返回类型相同。

- 如果 Lambda 表达式的正文有一条以上的语句必须包含在大括号(代码块)中,且表达式的返回值类型要与匿名函数的返回类型相同。

方法引用

使用 Lambda 表达式,我们已经看到代码可以变得非常简洁。

例如,要创建一个比较器,以下语法就足够了

Comparator c = (Person p1, Person p2) -> p1.getAge().compareTo(p2.getAge());

然后,使用类型推断:

Comparator c = (p1, p2) -> p1.getAge().compareTo(p2.getAge());

但是,我们可以使上面的代码更具表现力和可读性吗?我们来看一下:

Comparator c = Comparator.comparing(Person::getAge);

使用 :: 运算符作为 Lambda 调用特定方法的缩写,并且拥有更好的可读性。

使用方式

双冒号(::)操作符是 Java 中的方法引用。当们使用一个方法的引用时,目标引用放在::之前,目标引用提供的方法名称放在::之后,即 目标引用::方法。比如:

Person::getAge;

Person 类中定义的方法 getAge 的方法引用。

然后我们可以使用 Function 对象进行操作:

// 获取 getAge 方法的 Function 对象
Function<Person, Integer> getAge = Person::getAge;
// 传参数调用 getAge 方法
Integer age = getAge.apply(p);

我们引用 getAge,然后将其应用于正确的参数。

目标引用的参数类型是 Function,T 表示传入类型,R 表示返回类型。比如,表达式person -> person.getAge();,传入参数是person,返回值是 person.getAge(),那么方法引用 Person::getAge 就对应着 Function 类型

【函数式接口】

函数式接口定义

  • 带有@FunctionInterface注解的接口是函数式接口,编译器会对其做编译检查,不符合条件会报错
  • 函数式接口允许默认方法存在 default-method
  • 函数式接口允许静态方法存在 static-method
  • 函数式接口允许对Object方法的重写例如 toString() equals()

线程接口Runnable就是一个典型的函数式接口

package java.lang;
/**
 * The <code>Runnable</code> interface should be implemented by any
 * class whose instances are intended to be executed by a thread. The
 * class must define a method of no arguments called <code>run</code>.
 * <p>
 * This interface is designed to provide a common protocol for objects that
 * wish to execute code while they are active. For example,
 * <code>Runnable</code> is implemented by class <code>Thread</code>.
 * Being active simply means that a thread has been started and has not
 * yet been stopped.
 * <p>
 * In addition, <code>Runnable</code> provides the means for a class to be
 * active while not subclassing <code>Thread</code>. A class that implements
 * <code>Runnable</code> can run without subclassing <code>Thread</code>
 * by instantiating a <code>Thread</code> instance and passing itself in
 * as the target.  In most cases, the <code>Runnable</code> interface should
 * be used if you are only planning to override the <code>run()</code>
 * method and no other <code>Thread</code> methods.
 * This is important because classes should not be subclassed
 * unless the programmer intends on modifying or enhancing the fundamental
 * behavior of the class.
 *
 * @author  Arthur van Hoff
 * @see     java.lang.Thread
 * @see     java.util.concurrent.Callable
 * @since   JDK1.0
 */
@FunctionalInterface
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

我们也可以自己定义函数式接口,定义一个接口,使用lambda表达式传递接口并且调用

/**
 * 函数式接口
 */
@FunctionalInterface //只是为了编译器检查 可以不写
public interface MyInterface {
    // 有且只有一个抽象方法
    void sayHello(String name);
    //1.可以重写 Object的toString方法
    @Override
    String toString();
    // 也可以重写 Object的equals方法,还可以重写其他方法,这里只举个例子
    @Override
    boolean equals(Object object);
    //2 可以有默认方法
    default void sayHi(String name) {
        System.out.println("hi :" + name);
    }
    //3 可以有静态方法
    static boolean isEqual(Object obj) {
    return (null == obj)
            ? true
            : false;
    }
}

--------------------------------------

@Test
public void test() {
    // 调用 需要一个String参数 然后打印输出
    say("black猫", (name) -> System.out.println(name + ": hello"));
}
/**
  * 声明一个 接口传递方法
  * @param name 接口需要的参数
  * @param myInterface 是函数式类型接口 
  */
public void say(String name, MyInterface<String> myInterface) {
    myInterface.sayHello(name);
}

其实我们不用自己定义这些函数式接口,java8给我们内置好了一些接口如下:

  • 消费型接口 Consumer:void accept(T t);
  • 供给型接口 Supplier:T get();
  • 函数型接口 Function<T,R>:R apply(T t);
  • 断言型接口 Predicate:boolean test(T t);

消费型接口Consumer

Consumer接口除了一个抽象方法accept(T t)还有一个默认实现的andThen(Consumer consumer),用来在前一个消费接口调用完accept()后使用,可以理解为一个连续性操作。

package java.util.function;
import java.util.Objects;
/**
 * Represents an operation that accepts a single input argument and returns no
 * result. Unlike most other functional interfaces, {@code Consumer} is expected
 * to operate via side-effects.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #accept(Object)}.
 *
 * @param <T> the type of the input to the operation
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Consumer<T> {
    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
    /**
     * Returns a composed {@code Consumer} that performs, in sequence, this
     * operation followed by the {@code after} operation. If performing either
     * operation throws an exception, it is relayed to the caller of the
     * composed operation.  If performing this operation throws an exception,
     * the {@code after} operation will not be performed.
     *
     * @param after the operation to perform after this operation
     * @return a composed {@code Consumer} that performs in sequence this
     * operation followed by the {@code after} operation
     * @throws NullPointerException if {@code after} is null
     */
    default Consumer<T> andThen(Consumer<? super T> after) {
        Objects.requireNonNull(after);
        return (T t) -> { accept(t); 
        after.accept(t);
         };
    }
}

消费型接口Consumer的三个例子

1.Consumer接口的accept消费一个参数(反转字符串)

@Test
public void  test01(){
  testConsumer01("hello",(msg)->System.out.println(new StringBuffer(msg).reverse().toString());
}

//调用 accept
public void testConsumer01(String str,Consumer<String> consumer){
    consumer.accept(str);
}

2.两个消费接口 调用accept,实现一个输出字符串大写,一个输出字符串输出小写

@Test
public void test02(){
    testConsumer02("Hello Lambda",(str)->{
        System.out.println(str.toUpperCase());
    },(str)->{
        System.out.println(str.toLowerCase());
    }
    );
}
//两个消费接口 调用 accept
public void testConsumer02(String str,Consumer<String> consumer1,Consumer<String> consumer2){
    consumer1.accept(str);
    consumer2.accept(str);
}

3.两个消费接口的accept和andThen组合操作字符

@Test
public void test03() {
    String[] names = {"张山,男", "李诗,女", "王武,男", "马柳,女"};
    testConsumer03(names, (str) -> {
                System.out.print(str.split(",")[0]+":");
            }, (str) -> {
                System.out.println(str.split(",")[1]);
            }
    );
}
public void testConsumer03(String[] names, Consumer<String> consumer1, Consumer<String> consumer2) {
    for (int i = 0; i < names.length; i++) {
        //第一个消费接口处理完,第二个消费接口接着处理
        consumer1.andThen(consumer2).accept(names[i]);
    }
}

供给型接口Supplier

提供一个抽象方法get(),返回一个T

package java.util.function;
/**
 * Represents a supplier of results.
 *
 * <p>There is no requirement that a new or distinct result be returned each
 * time the supplier is invoked.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #get()}.
 *
 * @param <T> the type of results supplied by this supplier
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Supplier<T> {
    /**
     * Gets a result.
     *
     * @return a result
     */
    T get();
}

供给型接口Supplier的例子

利用供给型接口获取10个100内随机数,输出

@Test
public void test04() {
    ArrayList<Integer> arr = testSupplier02(10, () -> (int) (Math.random()*100));
    for (int i = 0; i < arr.size(); i++) {
        System.out.println(i + arr.get(i));
    }
}

public ArrayList<Integer> testSupplier02(int size, Supplier<Integer> consumer) {
    ArrayList<Integer> arr = new ArrayList<>();
    for (int i = 0; i < size; i++) {
        int str = consumer.get();
        arr.add(str);
    }
    return arr;
}

函数型接口Function

提供一个抽象方法apply(T t),返回一个R,Function<T,V> compose(Function function)在apply前执行,Function<T,V> andThen(Function function)在apply之后执行。

package java.util.function;
import java.util.Objects;
/**
 * Represents a function that accepts one argument and produces a result.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #apply(Object)}.
 *
 * @param <T> the type of the input to the function
 * @param <R> the type of the result of the function
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Function<T, R> {
    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
    /**
     * Returns a composed function that first applies the {@code before}
     * function to its input, and then applies this function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of input to the {@code before} function, and to the
     *           composed function
     * @param before the function to apply before this function is applied
     * @return a composed function that first applies the {@code before}
     * function and then applies this function
     * @throws NullPointerException if before is null
     *
     * @see #andThen(Function)
     */
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    /**
     * Returns a composed function that first applies this function to
     * its input, and then applies the {@code after} function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of output of the {@code after} function, and of the
     *           composed function
     * @param after the function to apply after this function is applied
     * @return a composed function that first applies this function and then
     * applies the {@code after} function
     * @throws NullPointerException if after is null
     *
     * @see #compose(Function)
     */
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    /**
     * Returns a function that always returns its input argument.
     *
     * @param <T> the type of the input and output objects to the function
     * @return a function that always returns its input argument
     */
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}

函数型接口Function例子

把一个字符串,先转大写然后反转,最后转小写打印,采用三个函数型接口参数

@Test
public void test3() {
    String msg = textFunction("hello-LAmbda", (str1) -> {
        return  str1.toUpperCase();
    },(str1)->{
        return str1.toLowerCase();
    },(str1)->{
        return new StringBuilder(str1).reverse().toString();
    });
    System.out.println(msg);
}

public String textFunction(String str, Function<String, String> function, Function<String, String> function2, Function<String, String> function3) {
    // function先执行然后是function2,但是function3在function2之前执行所以function2最后执行~~~
    return function.andThen(function2.compose(function3)).apply(str);
}

断言型接口 Predicate

一个抽象方法test(Test t),默认方法 and(Predicate predicate)/or(Predicate predicate)/negate(Predicate predicate)静态方法isEqual(Object targetRef)

package java.util.function;
import java.util.Objects;
/**
 * Represents a predicate (boolean-valued function) of one argument.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #test(Object)}.
 *
 * @param <T> the type of the input to the predicate
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);

    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * AND of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is {@code false}, then the {@code other}
     * predicate is not evaluated.
     *
     * <p>Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * {@code other} predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ANDed with this
     *              predicate
     * @return a composed predicate that represents the short-circuiting logical
     * AND of this predicate and the {@code other} predicate
     * @throws NullPointerException if other is null
     */
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }

    /**
     * Returns a predicate that represents the logical negation of this
     * predicate.
     *
     * @return a predicate that represents the logical negation of this
     * predicate
     */
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }

    /**
     * Returns a composed predicate that represents a short-circuiting logical
     * OR of this predicate and another.  When evaluating the composed
     * predicate, if this predicate is {@code true}, then the {@code other}
     * predicate is not evaluated.
     *
     * <p>Any exceptions thrown during evaluation of either predicate are relayed
     * to the caller; if evaluation of this predicate throws an exception, the
     * {@code other} predicate will not be evaluated.
     *
     * @param other a predicate that will be logically-ORed with this
     *              predicate
     * @return a composed predicate that represents the short-circuiting logical
     * OR of this predicate and the {@code other} predicate
     * @throws NullPointerException if other is null
     */
    default Predicate<T> or(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) || other.test(t);
    }

    /**
     * Returns a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}.
     *
     * @param <T> the type of arguments to the predicate
     * @param targetRef the object reference with which to compare for equality,
     *               which may be {@code null}
     * @return a predicate that tests if two arguments are equal according
     * to {@link Objects#equals(Object, Object)}
     */
    static <T> Predicate<T> isEqual(Object targetRef) {
        return (null == targetRef)
                ? Objects::isNull
                : object -> targetRef.equals(object);
    }
}

断言型接口Predicate例子

判断一个字符串是否包含‘*’并且长度大于10 或者 字符串包含‘-’

public void test4() {
    String str = "hello-lambda";
    boolean bool = textPredicate(str, (msg) -> {
        return msg.indexOf('*') > -1;
    }, (msg) -> {
        return msg.length() > 10;
    }, (msg) -> {
        return msg.indexOf("-") > -1;
    });
    System.out.println(bool);
}

public boolean textPredicate(String str, Predicate<String> predicate, Predicate<String> predicate2, Predicate<String> predicate3) {
    return predicate.and(predicate2).or(predicate3).test(str);
}

其他接口

根据上面的示例,每个接口结合源码可以写出自己想要的代码

函数式接口 参数类型 返回类型 用途
BiFunction<T, U, R> T, U R 对类型为 T, U 参数应用 操作,返回 R 类型的结 果。包含方法为 R apply(T t, U u);
UnaryOperator (Function子接口) T T 对类型为T的对象进行一 元运算,并返回T类型的 结果。包含方法为 T apply(T t);
BinaryOperator (BiFunction 子接口) T, T T 对类型为T的对象进行二 元运算,并返回T类型的 结果。包含方法为 T apply(T t1, T t2);
BiConsumer<T, U> T, U void 对类型为T, U 参数应用 操作。包含方法为 void accept(T t, U u)
ToIntFunction ToLongFunction ToDoubleFunction T int long double 分别计算int、long、 double、值的函数
IntFunction LongFunction DoubleFunction int long double R 参数分别为int、long、 double 类型的函数

【Stream API】

Stream是Java8中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。
使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数 据库查询。
也可以使用Stream API来并行执行操作。
简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。

Stream流是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列,以下三点注意。

Stream 自己不会存储元素。
Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

Stream流操作的三大步

创建Stream流
中间操作
终止操作

创建Stream流

集合创建Stream流

/****
 * java8中的Collection接口方法
 * stream() 顺序流
 * parallelStream()  并行流(后面再说这个)
 */
@Test
public void test01() {
    //声明一个list
    List<String> list = new ArrayList<String>();
    //  default Stream<E> stream() 顺序流
    //  default Stream<E> parallelStream()  并行流
    //  创建一个顺序流
    Stream stream1 = list.stream();
    //  创建一个并行流
    Stream stream2 = list.parallelStream();
}

数组创建Stream流

/****
 * 数组创建Stream流
 * Java8 中的 Arrays 的静态方法 stream() 可以获取数组流
 */
@Test
public void test02() {
    //   Java8 中的 Arrays 的静态方法 stream() 可以获取数组流
    //    public static <T> Stream<T> stream(T[] array)
    String[] arr = new String[10];
    Stream stream = Arrays.stream(arr);
}

由值创建Stream流 Stream.of()

/****
 * 由值创建Stream流
 * Stream.of()
 */
@Test
public void test03() {
    //  可以使用静态方法 Stream.of(), 通过显式值创建一个流。它可以接收任意数量的参数。
    Stream stream = Stream.of("1", "2", "3", "4");
}

Stream.iterate() 和 Stream.generate()

/****
 * 由函数创建Stream无限流
 *
 * seed种子  f 一元运算接口
 * Stream.iterate(T seed,UnaryOperator f)
 *
 * supplier 供给型型接口
 * Stream.generate(Supplier supplier)
 */
@Test
public void test04() {
    // 可以使用静态方法 Stream.iterate() 和 Stream.generate(), 创建无限流。
    //  args1 seed 开始种子, args2 一元函数式接口
    //迭代  public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
    Stream stream1 = Stream.iterate(0, (x) -> x + 1);

    //args 一个供给型接口
    // 生成   public static<T> Stream<T> generate(Supplier<T> s) :
    Stream stream2 = Stream.generate(() -> new Random().nextInt(100));

}

中间操作

多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理,而在终止操作时一次性全部处理,称为“惰性求值”。看一下一些常用的API:

filter()

/****
    * filter(Predicate p)
    * 接收一个断言式接口,从流中排除不符合条件的元素
    */
   @Test
   public void test01() {
       Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
       //使用Stream流的静态方法 of创建一个Stream流
       Stream<Integer> stream = Stream.of(nums);
       //过滤操作 接收一个断言式接口 排除不符合条件的元素 输出结果
       stream.filter((x) -> x > 5).forEach(System.out::println);
   }

distinct()

/***
   * distinct()
   * 筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
   */
  @Test
  public void test02() {
      Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
      //使用Stream流的静态方法 of创建一个Stream流
      Stream<Integer> stream = Stream.of(nums);
      //去除重复的元素
      stream.distinct().forEach(System.out::println);
  }

limit()

/***
 * limit(long maxSize)
 * 接收一个long型数值流中的元素个数不操过maxSize个,
 */
@Test
public void test03() {
    //使用Stream流的静态方法 generate创建一个Stream无限流
    Stream stream = Stream.generate(() -> new Random().nextInt(100));
    //截断流获取前n个元素 最大n个
    stream.limit(10).forEach(System.out::println);
}

skip()

/***
 * skip(long n)
 * 接收一个long型数值 跳过流前n个元素获取后面的元素和 limit(n)相反
 */
@Test
public void test04() {
    Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    //使用Stream流的静态方法 generate创建一个Stream无限流
    Stream stream = Arrays.stream(nums);
    stream.skip(3).forEach(System.out::println);
}

map()

/****
 * map(Function f)
 * 接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
 */
@Test
public void test05() {
    Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    //使用Stream流的静态方法 generate创建一个Stream无限流
    Stream<Integer> stream = Arrays.stream(nums);
    // 将每个元素*2
    stream.map(x -> x * 2).forEach(System.out::println);

}

flatMap()

/****
 * flatMap(ToDoubleFunction f)
 * 接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
 */
@Test
public void test08() {
    String[] strings = {"hello lambda", "hello", "lambda"};
    //  Stream的静态方法 of获取流
    Stream<String> testStream = Stream.of(strings);
    //  流中的元素换成另一个流 分割处理 然后去重 打印
    testStream.flatMap(str -> Arrays.stream(str.split(" "))).distinct().forEach(System.out::println);
}

sorted()

/**
 * sorted()
 * 产生一个新流,其中按自然顺序排序
 */
@Test
public void test09() {
    Integer[] nums = {1, 4, 2, 6, 3, 0, 9, 8, 7, 5};
    Arrays.stream(nums).sorted().forEach(System.out::println);
}
/**
 * sorted(Comparator comparator)
 * 产生一个新流,其中按比较器顺序排序
 */
@Test
public void test10() {
    Integer[] nums = {-1, 4, -2, 6, -3, 0, 9, -8, 7, -5};
    //例如 按照绝对值排序
    Arrays.stream(nums).sorted(Comparator.comparing(x -> Math.abs(x))).forEach(System.out::println);
}

终止操作

终端操作会从流的流水线生成结果。 其结果可以是任何不是流的值,例如:List、Integer、boolean

allMatch()

/****
 * allMatch(Predicate predicate)
 * 接收一个断言式接口 全匹配 返回boolean
 */
@Test
public void test01() {
    Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    //使用Stream流的静态方法 of创建一个Stream流
    Stream<Integer> stream = Stream.of(nums);
    // 匹配数组元素是否全部大于等于0
    System.out.println(stream.allMatch((x) -> x >= 0));

}

anyMatch()

/****
 * anyMatch(Predicate predicate)
 * 接收一个断言式接口 至少匹配一个 返回boolean
 */
@Test
public void test02() {
    Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    //使用Stream流的静态方法 of创建一个Stream流
    Stream<Integer> stream = Stream.of(nums);
    // 匹配数组元素是否有大于10的元素
    System.out.println(stream.anyMatch((x) -> x > 10));
}

noneMatch()

/****
 * noneMatch(Predicate predicate)
 * 接收一个断言式接口 是否没有匹配的元素 返回boolean
 */
@Test
public void test03() {
    Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    //使用Stream流的静态方法 of创建一个Stream流
    Stream<Integer> stream = Stream.of(nums);
    // 匹配数组元素是否没有大于10的元素
    System.out.println(stream.noneMatch((x) -> x > 10));
}

findFirst()

/****
 * findFirst()
 * 返回Optional
 */
@Test
public void test04() {
    Integer[] nums = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    //使用数组Arrays创建流
    Stream stream = Arrays.stream(nums);
    //返回流元素中的第一个元素
    Optional optional = stream.findFirst();
    System.out.println(optional.get());
}

findAny()

/****
 * findAny()
 * 返回Optional
 */
@Test
public void test05() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    //使用数组Arrays创建流
    Stream stream = Arrays.stream(nums);
    //返回流元素中的任意元素
    Optional optional = stream.findAny();
    System.out.println(optional.get());
}

count()

/****
 * count()
 * 返回流元素总数 Long型
 */
@Test
public void test06() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    //使用数组Arrays创建流
    Stream stream = Arrays.stream(nums);
    Long aLong = stream.count();
    System.out.println(aLong);
}

max()

/****
 * max(Comparator comparator)
 * 返回流元素最大值
 * 接收一个比较器
 */
@Test
public void test07() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    //使用数组Arrays创建流
    Stream<Integer> stream = Arrays.stream(nums);
    //返回流元素中的最大元素
    Optional optional = stream.max(Integer::compare);
    System.out.println(optional.get());

}

min()

/****
 * max(Comparator comparator)
 * 返回流元素最小值
 * 接收一个比较器
 */
@Test
public void test08() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    //使用数组Arrays创建流
    Stream<Integer> stream = Arrays.stream(nums);
    //返回流元素中的最小元素
    Optional optional = stream.min(Integer::compare);
    System.out.println(optional.get());

}

forEach()

/****
 * forEach(Consumer consumer)
 * 接收一个消费性接口
 * 内部迭代(使用 Collection 接口需要用户去做迭代,称为外部迭代。
 * 相反,Stream API 使用内部 迭代——它帮你把迭代做了)
 */
@Test
public void test09() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    Arrays.stream(nums).forEach(System.out::println);
}

reduce()


/***
 * reduce(BinaryOperator<T> accumulator)
 * 可以将流中元素反复结合起来,得到一个值。返回Optional
 * 接收一个二元运算接口
 */
@Test
public void test10() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    //  依次累加
    Object object = Arrays.stream(nums).reduce((x, y) -> x + y).get();
    System.out.println(object);
}

/***
 * reduce(T iden, BinaryOperator<T> accumulator)
 * 接收一个二元运算接口
 * 可以将流中元素反复结合起来,得到一个值。返回 T
 */
@Test
public void test11() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    //  iden 作为一个值先加入运算然后 依次累加
    Object object = Arrays.stream(nums).reduce(10, (x, y) -> x * y);
    System.out.println(object);
}

stream.collect(Collectors.toList())

/***
 * collect(Collector collector)
 * 将流转换为其他形式。
 * 接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
 * Collectors 实用类提供了很多静态方法,可以方便地创建常见收集器实例
 * Collectors.toList()
 * // 将数组变成了 list
 */
@Test
public void test12() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};

    Stream<Integer> stream = Arrays.stream(nums);
    List list = stream.collect(Collectors.toList());
    // 将数组变成了 list
    System.out.println(list.size());
}

stream.collect(Collectors.toSet())

/***
 * Collectors.toSet()
 * 将数组变成了 set
 */
@Test
public void test13() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    Stream<Integer> stream = Arrays.stream(nums);
    Set set = stream.collect(Collectors.toSet());
    // 将数组变成了 set
    System.out.println(set.size());
}

stream.collect(Collectors.toSet())


/***
 * Collectors.toCollection(ArrayList::new)
 * Collectors.toCollection(HashSet::new)
 * 将数组变成了 Collection
 */
@Test
public void test14() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    Stream<Integer> stream = Arrays.stream(nums);
    Collection collection = stream.collect(Collectors.toCollection(HashSet::new));
    // 将数组变成了 collection
    System.out.println(collection.size());
}

stream.collect(Collectors.counting())


/***
 * Collectors.counting()
 * 计算流中元素的个数
 */
@Test
public void test15() {
    Integer[] nums = {2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 1};
    Stream<Integer> stream = Arrays.stream(nums);
    Long integer = stream.collect(Collectors.counting());
    System.out.println(integer);
}

stream.collect(Collectors.summingDouble())


/***
 * Collectors.summingDouble(ToDoubleFunction mapper)
 * 计算流中元素的对象的某一个属性平均值
 * 接收一个 计算int、long、 double、值的函数 接口
 */
@Test
public void test16() {
    List<Employee> employees = new ArrayList<>(3);
    Employee employe1 = new Employee(1, "A1", 5000);
    Employee employe2 = new Employee(1, "A2", 8000);
    Employee employe3 = new Employee(1, "A3", 10000);
    employees.add(employe1);
    employees.add(employe2);
    employees.add(employe3);
    Stream<Employee> stream = employees.stream();
    Double sumSalary = stream.collect(Collectors.summingDouble(Employee::getSalary));
    System.out.println(sumSalary);
}

stream.collect(Collectors.averagingDouble())


/***
 * Collectors.averagingDouble(ToDoubleFunction mapper)
 * 计算流中元素的对象的某一个属性平均值
 * 接收一个 计算int、long、 double、值的函数 接口
 */
@Test
public void test17() {
    List<Employee> employees = new ArrayList<>(3);
    Employee employe1 = new Employee(1, "A1", 5000);
    Employee employe2 = new Employee(1, "A2", 8000);
    Employee employe3 = new Employee(1, "A3", 10000);
    employees.add(employe1);
    employees.add(employe2);
    employees.add(employe3);
    Stream<Employee> stream = employees.stream();
    Double avgSalary = stream.collect(Collectors.averagingDouble(Employee::getSalary));
    System.out.println(avgSalary);
}

stream.collect(Collectors.joining())


/***
 * Collectors.joining()
 * 连接流中元素的对象的某一个属性字符串
 */
@Test
public void test18() {
    List<Employee> employees = new ArrayList<>(3);
    Employee employe1 = new Employee(1, "A1", 5000);
    Employee employe2 = new Employee(1, "A2", 8000);
    Employee employe3 = new Employee(1, "A3", 10000);
    employees.add(employe1);
    employees.add(employe2);
    employees.add(employe3);
    Stream<Employee> stream = employees.stream();
    String names = stream.map((x) -> x.getName() + "-").collect(Collectors.joining());
    System.out.println(names);
}

stream.collect(Collectors.minBy())


/***
 * Collectors.maxBy(Comparator comparator)
 * 根据比较器选择最小值
 * 接收一个比较器
 */
@Test
public void test19() {
    Integer[] nums = {1, 2, 3, 4, 5, 7, 8, 9, 3, 4, 56};
    Stream<Integer> stream = Arrays.stream(nums);
    Optional optional = stream.collect(Collectors.minBy(Integer::compareTo));
    System.out.println(optional.get());
}

stream.collect(Collectors.reducing())

    /***
     * Collectors.reducing(U identity,Function<? super T, ? extends U> mapper,BinaryOperator<U> op)
     * 从一个作为累加器的初始值开始,利用BinaryOperator与流中元素逐个结合,从而归约成单个值
     * 接收二元计算接口
     */
    @Test
    public void test20() {
        List<Employee> employees = new ArrayList<>(3);
        Employee employe1 = new Employee(1, "A1", 5000);
        Employee employe2 = new Employee(1, "A2", 8000);
        Employee employe3 = new Employee(1, "A3", 10000);
        employees.add(employe1);
        employees.add(employe2);
        employees.add(employe3);

        Stream<Employee> stream = employees.stream();
//        identity : 0d 类型和后面的元素类型 保持一致
        Double aDouble = stream.collect(Collectors.reducing(0d, Employee::getSalary, Double::sum));
        System.out.println(aDouble);
    }

stream.collect(Collectors.collectingAndThen())

    /***
     *  Collectors.collectingAndThen(Collector<T,A,R> downstream,Function<R,RR> finisher)
     *  转换函数返回的类型
     *  包裹另一个收集器,对其结果转换函数
     */
    @Test
    public void test21() {
        List<Employee> employees = new ArrayList<>(3);
        Employee employe1 = new Employee(1, "A1", 5000);
        Employee employe2 = new Employee(1, "A2", 8000);
        Employee employe3 = new Employee(1, "A3", 10000);
        employees.add(employe1);
        employees.add(employe2);
        employees.add(employe3);
        Stream<Employee> stream = employees.stream();
//        转换函数返回的类型 返回set
//        包裹另一个收集器,对其结果 set 进行处理 判断时候为空
        Boolean bool = stream.collect(Collectors.collectingAndThen(Collectors.toSet(), Set::isEmpty));
        System.out.println(bool);
    }

stream.collect(Collectors.groupingBy())

/***
 *  根据某属性值对流分组,属 性为K,结果为V
 *  Collectors.groupingBy(Function<? super T, ? extends K> classifier)
 *  传入一个 代表流元素的属性
 *  返回 以属性为key value为 list的map
 */
@Test
public void test22() {
    List<Employee> employees = new ArrayList<>(3);
    Employee employe1 = new Employee(1, "A1", 5000);
    Employee employe2 = new Employee(1, "A2", 8000);
    Employee employe3 = new Employee(1, "A3", 10000);
    employees.add(employe1);
    employees.add(employe2);
    employees.add(employe3);
    Stream<Employee> stream = employees.stream();
    Map map = stream.collect(Collectors.groupingBy(Employee::getName));
    Set set=map.entrySet();
    for (Object str:set) {
        System.out.println(str);
        System.out.println(map.get(str));
    }

}

stream.collect(Collectors.partitioningBy())

/***
 *  根据true或false进行分区
 *  Collectors.groupingBy(Function<? super T, ? extends K> classifier)
 *  传入一个 代表流元素的属性
 *  返回 以属性(flase/true)为key value为 list的map
 */
@Test
public void test23() {
    List<Employee> employees = new ArrayList<>(3);
    Employee employe1 = new Employee(1, "A1", 5000,false);
    Employee employe2 = new Employee(1, "A2", 8000,true);
    Employee employe3 = new Employee(1, "A3", 10000,false);
    employees.add(employe1);
    employees.add(employe2);
    employees.add(employe3);
    Stream<Employee> stream = employees.stream();
    Map map = stream.collect(Collectors.partitioningBy(Employee::getFlag));
    Set set=map.entrySet();
    for (Object str:set) {
        System.out.println(str);
        System.out.println(map.get(str));
    }

}


施工中...

您的喜欢是作者写作最大的动力!❤️
  • PayPal
  • AliPay
  • WeChatPay
  • QQPay
YAN