JDK8中的新特性

1.lambda表达式

1.定义

Java 8 发布的最重要新特性。Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中),可以推导出来的就可以省略了,Lambda 表达式免去了使用匿名方法的麻烦,并且给予Java简单但是强大的函数化的编程能力。

2.例子
//一个线程的创建可以使用这种方法
new Thread(() -> System.out.println("多线程任务执行!")).start();
3.标准格式

标准格式3个部分:
一些参数
一个箭头
一段代码

(参数类型 参数名称) ‐> { 代码语句 } 强调的是做什么而不是怎么做

Runnable接口简化:
1. () ‐> System.out.println("多线程任务执行!")
Comparator接口简化:
2. Arrays.sort(array, (a, b) ‐> a.getAge() ‐ b.getAge());
4.前提条件
1.必须有接口,接口中有且仅有一个方法 --函数式接口一定可以的(但不限于)
2.必须有固定的格式,就是参数什么的固定的,可以推断出来
3.

2.Stream流

1.什么是stream流

​ Stream流不同于InputStream和OutputStream.Jdk8中的Stream流是对集合(Collerction)的增强,增强了对集合对象的聚合操作,Stram API借助于Lambda表达式,他提供了串行和并行使用fork/join并行来拆分

2.常用
1.集合获取stream流的方式
	Stream<T> stream()
	Stream<T> parallelStream()
2. 数组获取stream流的方式
	Stream<T> Stream.of(T[])
	Stream<T> Arrays.stream(T[]);
3. 文件获取stream流
	BufferedReader bufferedReader = new BufferedReader(new FileReader("README.md"));
	Stream<String> linesStream = bufferedReader.lines();
4.静态方法获取流操作
	IntStream rangeStream = IntStream.range(1, 10);
    rangeStream.limit(10).forEach(num -> System.out.print(num+","));
    IntStream intStream = IntStream.of(1, 2, 3, 3, 4);
    intStream.forEach(num -> System.out.print(num+","));
Pipelining中间操作都会返回流对象本身,这样多个操作可以串联成一个管道

forEach() --输出
map --方法用于映射每个元素到对应的结果
filter --方法用于通过设置的条件过滤出元素
limit --获取指定数量的流
public class StreamDemo1 {
    public static void main(String[] args) throws FileNotFoundException {
        demo1();
    }
    public static void getStream() throws FileNotFoundException {
        List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
        String[] nameArr = {"Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter"};
        // 集合获取 Stream 流
        Stream<String> nameListStream = nameList.stream();
        // 集合获取并行 Stream 流
        Stream<String> nameListStream2 = nameList.parallelStream();
        // 数组获取 Stream 流
        Stream<String> nameArrStream = Stream.of(nameArr);
        // 数组获取 Stream 流
        Stream<String> nameArrStream1 = Arrays.stream(nameArr);
        // 文件流获取 Stream 流
        BufferedReader bufferedReader = new BufferedReader(new FileReader("README.md"));
        Stream<String> linesStream = bufferedReader.lines();

        // 从静态方法获取流操作
        IntStream rangeStream = IntStream.range(1, 10);
        rangeStream.limit(10).forEach(num -> System.out.print(num+","));
        IntStream intStream = IntStream.of(1, 2, 3, 3, 4);
        intStream.forEach(num -> System.out.print(num+","));
    }

    /**
     * 1. 筛选出名字长度为4的
       2. 名字前面拼接 This is
       3. 遍历输出
     */
    public static void demo1(){
        List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
        nameList.stream()
                .filter(name -> name.length() == 4)
                .map(name -> "This is "+name)
                .forEach(name -> System.out.println(name));
    }
    /**
     * 转换成为大写然后收集结果,遍历输出
     */
    public static void demo2(){
        List<String> nameList = Arrays.asList("Darcy", "Chris", "Linda", "Sid", "Kim", "Jack", "Poul", "Peter");
        List<String> collect = nameList.stream()
                .map(String::toUpperCase)
                .collect(Collectors.toList());
        collect.forEach(name-> System.out.println(name+","));
    }
    /**
     * 把数字值乘以2
     */
    public void mapTest() {
        List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        // 映射成 2倍数字
        List<Integer> collect = numberList.stream()
                .map(number -> number * 2)
                .collect(Collectors.toList());
        collect.forEach(number -> System.out.print(number + ","));
        System.out.println();
        numberList.stream()
                .map(number -> "数字 " + number + ",")
                .forEach(number -> System.out.print(number));
    }
    /**
     * flatmap把对象扁平化
     */
    public void flatMapTest() {
        Stream<List<Integer>> inputStream = Stream.of(
                Arrays.asList(1),
                Arrays.asList(2, 3),
                Arrays.asList(4, 5, 6)
        );
        List<Integer> collect = inputStream
                .flatMap((childList) -> childList.stream())
                .collect(Collectors.toList());
        collect.forEach(number -> System.out.print(number + ","));
    }

    /**
     * 遍历输出
     */
    public void forEachTest(){
        List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        numberList.stream().forEach(number -> System.out.print(number+","));
    }

    /**
     * filter 数据筛选
     * 筛选出偶数数字
     */
    public void filterTest() {
        List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        List<Integer> collect = numberList.stream()
                .filter(number -> number % 2 == 0)
                .collect(Collectors.toList());
        collect.forEach(number -> System.out.print(number + ","));
    }

    /**
     * 查找第一个数据
     * 返回的是一个 Optional 对象
     */
    public void findFirstTest(){
        List<Integer> numberList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        Optional<Integer> firstNumber = numberList.stream()
                .findFirst();
        System.out.println(firstNumber.orElse(-1));
    }

    /**
     * Stream 转换为其他数据结构
     */
    public void collectTest() {
        List<Integer> numberList = Arrays.asList(1, 1, 2, 2, 3, 3, 4, 4, 5);
        // to array
        Integer[] toArray = numberList.stream()
                .toArray(Integer[]::new);
        // to List
        List<Integer> integerList = numberList.stream()
                .collect(Collectors.toList());
        // to set
        Set<Integer> integerSet = numberList.stream()
                .collect(Collectors.toSet());
        System.out.println(integerSet);
        // to string
        String toString = numberList.stream()
                .map(number -> String.valueOf(number))
                .collect(Collectors.joining()).toString();
        System.out.println(toString);
        // to string split by ,
        String toStringbJoin = numberList.stream()
                .map(number -> String.valueOf(number))
                .collect(Collectors.joining(",")).toString();
        System.out.println(toStringbJoin);
    }

    /**
     * 使用流操作和不使用流操作的编码风格对比
     */
    public void diffTest() {
        // 不使用流操作
        List<String> names = Arrays.asList("Jack", "Jill", "Nate", "Kara", "Kim", "Jullie", "Paul", "Peter");
        // 筛选出长度为4的名字
        List<String> subList = new ArrayList<>();
        for (String name : names) {
            if (name.length() == 4) {
                subList.add(name);
            }
        }
        // 把值用逗号分隔
        StringBuilder sbNames = new StringBuilder();
        for (int i = 0; i < subList.size() - 1; i++) {
            sbNames.append(subList.get(i));
            sbNames.append(", ");
        }
        // 去掉最后一个逗号
        if (subList.size() > 1) {
            sbNames.append(subList.get(subList.size() - 1));
        }
        System.out.println(sbNames);
        System.out.println("----------------");

        // 使用 Stream 流操作
        String nameString = names.stream()
                .filter(num -> num.length() == 4)
                .collect(Collectors.joining(", "));
        System.out.println(nameString);

        // String string = names.stream().filter(num -> num.length() == 4).map(name -> name.toUpperCase()).collect(Collectors.joining(","));
        String string = names.stream()
                .filter(num -> num.length() == 4)
                .map(name -> name.toUpperCase())
                .collect(Collectors.joining(","));
    }

    /**
     * reduce 字符串拼接例子
     */
    public void reduceTest() {
        List<String> skills = Arrays.asList("java", "golang", "c++", "c", "python");
        String s = skills.stream().reduce((all, skill) -> all + skill).get();
        System.out.println(s);
    }

    /**
     * 数据去重例子
     */
    public void distinctTest() {
        List<String> skills = Arrays.asList("java", "golang", "c++", "c", "python", "java");
        List<String> collects = skills.stream().distinct().collect(Collectors.toList());
        collects.forEach(skill -> System.out.println(skill));
        System.out.println("---------------------------------------------");
        skills = Arrays.asList("java", "golang", "c++", "c", "python", "java");
        skills.stream().distinct().forEach(s -> System.out.println(s));
    }

    /**
     * 数学计算测试
     */
    public void mathTest() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        IntSummaryStatistics stats = list.stream().mapToInt(x -> x).summaryStatistics();
        System.out.println("最小值:" + stats.getMin());
        System.out.println("最大值:" + stats.getMax());
        System.out.println("个数:" + stats.getCount());
        System.out.println("和:" + stats.getSum());
        System.out.println("平均数:" + stats.getAverage());
    }

    /**
     * 按年龄分组
     */
    public void groupByTest() {
        List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
        Map<String, List<Integer>> ageGrouyByMap = ageList.stream()
                .collect(Collectors.groupingBy(age -> String.valueOf(age / 10)));

        ageGrouyByMap.forEach((k, v) -> {
            System.out.println("年龄" + k + "0多岁的有:" + v);
        });
    }

    /**
     * 按某个条件分组
     * 给一组年龄,分出成年人和未成年人
     */
    public void partitioningByTest() {
        List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
        Map<Boolean, List<Integer>> ageMap = ageList.stream()
                .collect(Collectors.partitioningBy(age -> age > 18));
        System.out.println("未成年人:" + ageMap.get(false));
        System.out.println("成年人:" + ageMap.get(true));
    }

    /**
     * 生成自己的 Stream 流
     */
    public void generateTest(){
        // 生成自己的随机数流
        Random random = new Random();
        Stream<Integer> generateRandom = Stream.generate(random::nextInt);
        generateRandom.limit(5).forEach(System.out::println);

        // 生成自己的 UUID 流
        Stream<UUID> generate = Stream.generate(UUID::randomUUID);
        generate.limit(5).forEach(System.out::println);
    }


    /**
     * 获取 / 扔掉前 n 个元素
     */
    public void limitOrSkipTest() {
        // 生成自己的随机数流
        List<Integer> ageList = Arrays.asList(11, 22, 13, 14, 25, 26);
        ageList.stream()
                .limit(3)
                .forEach(age -> System.out.print(age+","));
        System.out.println();

        ageList.stream()
                .skip(3)
                .forEach(age -> System.out.print(age+","));
    }

    /**
     * 找出偶数
     */
    public void lazyTest() {
        // 生成自己的随机数流
        List<Integer> numberLIst = Arrays.asList(1, 2, 3, 4, 5, 6);
        // 找出第一个偶数
        Stream<Integer> integerStream = numberLIst.stream()
                .filter(number -> {
                    int temp = number % 2;
                    if (temp == 0 ){
                        System.out.println(number);
                    }
                    return temp == 0;
                });

        System.out.println("分割线");
        List<Integer> collect = integerStream.collect(Collectors.toList());
    }

    /**
     * 并行计算
     */
    public void main() {
        // 生成自己的随机数流,取一千万个随机数
        Random random = new Random();
        Stream<Integer> generateRandom = Stream.generate(random::nextInt);
        List<Integer> numberList = generateRandom.limit(10000000).collect(Collectors.toList());

        // 串行 - 把一千万个随机数,每个随机数 * 2 ,然后求和
        long start = System.currentTimeMillis();
        int sum = numberList.stream().map(number -> number * 2).mapToInt(x -> x).sum();
        long end = System.currentTimeMillis();
        System.out.println("串行耗时:"+(end - start)+"ms,和是:"+sum);

        // 并行 - 把一千万个随机数,每个随机数 * 2 ,然后求和
        start = System.currentTimeMillis();
        sum = numberList.parallelStream().map(number -> number * 2).mapToInt(x -> x).sum();
        end = System.currentTimeMillis();
        System.out.println("并行耗时:"+(end - start)+"ms,和是:"+sum);

    }

    public void simpleTest(){
        List<Integer> numbers = Arrays.asList(1, 2, 3);
        int[] factor = new int[] { 2 };
        Stream<Integer> stream = numbers.stream()
                .map(e -> e * factor[0]);
        factor[0] = 0;
        stream.forEach(System.out::println);
    }


}

3.函数式接口

1.定义

函数式接口就是有且仅有一个抽象方法的接口,java中的函数式编程就是Lambda,函数式接口可以使用于lambda表达式中,

2.格式
修饰符 interface 接口名称 {
public abstract 返回值类型 方法名称(可选参数信息);
// 其他非抽象方法内容 
//public abstract 在抽象接口中的方法修饰上是可以省略的
}
3.例子
public interface MyFunctionalInterface {
 void myMethod();
}
public class FunctionalInterface {
    // 使用自定义的函数式接口作为方法参数
    private static void doSomething(MyFunctionalInterface inter) {
        inter.myMethod(); // 调用自定义的函数式接口方法
    }
    public static void main(String[] args) {
// 调用使用函数式接口的方法
        doSomething(()-> System.out.println("Lambda执行啦!"));
    }
}
4.自定义
与@Override 注解的作用类似,Java 8中专门为函数式接口引入了一个新的注解: @FunctionalInterface。该注解可用于一个接口的定义上
如果不使用这个注解,如果仍然满足要求,一样可以用,但是加上就必须满足,不然会报错
5.常用 java.util.function
1.Supplier接口

java.util.function.Supplier 对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据

@FunctionalInterface
public interface Supplier<T> {
    T get();
}
调用这个方法就要返回一个T类型的数据,至于这个数据是如何加工出来的,可以自定义,所以是生产者

例子

public interface MyFunctionalInterface {
    void myMethod();
}

public class FunctionalInterface {
    // 使用自定义的函数式接口作为方法参数
    private static void doSomething(MyFunctionalInterface inter) {
        inter.myMethod(); // 调用自定义的函数式接口方法
    }
    public static void main(String[] args) {
        // 调用使用函数式接口的方法
        doSomething(()-> System.out.println("Lambda执行啦!"));
    }
}

2.Consumer接口

java.util.function.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); };
    }
}

例子

public class ConsumerDemo {
    private static void consumeString(Consumer<String> one,Consumer<String> two) {
       one.andThen(two).accept("hello");
       one.accept("ddd");
    }

    public static void main(String[] args) {
        consumeString(s-> System.out.println(s.toUpperCase()),s-> System.out.println(s.toLowerCase()));
    }
}

3.Predicate接口

java.util.function.Predicate 有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。

@FunctionalInterface
public interface Predicate<T> {
    //用于判断
    boolean test(T t);

    //既然是条件判断,就会存在与、或、非三种常见的逻辑关系。其中将两个 Predicate 条件使用“与”逻辑连接起     //来实现“并且”的效果时,可以使用default方法 and 
    default Predicate<T> and(Predicate<? super T> other) {
        Objects.requireNonNull(other);
        return (t) -> test(t) && other.test(t);
    }
    
    //它是执行了test方法之后,对结果boolean值进行“!”取反而已。一定要在调用test方法之前调用negate
    default Predicate<T> negate() {
        return (t) -> !test(t);
    }
    
    //or或者进行比较 在调用test之前调用or
    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);
    }
}

public class PredicateAndTest {
    public static void main(String[] args) {
        //methodAnd(s-> s.contains("H"), s-> s.contains("y"),"Helloworld");
        //methodOr(s-> s.contains("a"), s-> s.contains("y"),"Helloworld");
        methodNegate(s-> "Helloworld".equals(s),"Helloworld");
    }
    private static void methodAnd(Predicate<String> one,Predicate<String> two,String str)     {
        boolean test = one.and(two).test(str);
        System.out.println("字符串符合要求吗:" + test);
    }
    private static void methodOr(Predicate<String> one,Predicate<String> two,String str){
        boolean test = one.or(two).test(str);
        System.out.println("字符串符合要求吗or:" + test);
    }
    private static void methodNegate(Predicate<String> one,String str){
        boolean test = one.negate().test(str);
        System.out.println("字符串取反:" + test);
    }
}


4.Function<T,R> 接口

简单的说就是类型转换,就是一种类型的数据转换成为另外一个类型的数据,把T类型的转换成R类型的,有进有出

@FunctionalInterface
public interface Function<T, R> {
    //根据类型T的参数获取类型R的结果
    R apply(T t);

   
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    //用来进行组合操作 类似于Consumer 中的andThen
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }

   
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}


例子

public class FunctionDemo {
    public static void main(String[] args) {
       method(s -> Integer.parseInt(s),"10");
       method2(new Function<String, Integer>() {
           @Override
           public Integer apply(String s) {
               return 1;
           }
       });
        methodAddthen(s -> Integer.parseInt(s),s->s+10,"1");
    }
    //String 转换成Integer类型的
    private static void method(Function<String, Integer> function, String str) {
        int num = function.apply(str);
        System.out.println(num + 20);
    }
    private static void method2(Function<String, Integer> function) {
        int num = function.apply("33");
        System.out.println(num + 20);
    }
    private static void methodAddthen(Function<String, Integer> one,Function<Integer, Integer> two,String str) {
        Integer apply1 = one.andThen(two).apply(str);
        System.out.println(apply1 + 20);
    }
}


posted @ 2020-01-20 14:25  这都没什么  阅读(206)  评论(0编辑  收藏  举报